home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / packages / crypt.el.z / crypt.el
Encoding:
Text File  |  1998-05-21  |  109.2 KB  |  2,640 lines

  1. ;;; crypt.el --- code for handling all sorts of compressed and encrypted files
  2.  
  3. ;; Author: Lawrence R. Dodd <dodd@roebling.poly.edu>
  4. ;;    Rod Whitby <rwhitby@research.canon.oz.au>
  5. ;;    Kyle E. Jones <kyle@uunet.uu.net>
  6. ;; Maintainer: Lawrence R. Dodd <dodd@roebling.poly.edu>
  7. ;; Created: crypt.el in 1988, crypt++.el on 18 Jan 1993
  8. ;; Version: 2.83
  9. ;; Date: 1994/03/31 12:30:17
  10. ;; Keywords: extensions
  11.  
  12. ;;; Copyright (C) 1994 Lawrence R. Dodd
  13. ;;; Copyright (C) 1993 Lawrence R. Dodd and Rod Whitby
  14. ;;; Copyright (C) 1988, 1989, 1990 Kyle E. Jones
  15. ;;;  
  16. ;;; This program is free software; you can redistribute it and/or modify
  17. ;;; it under the terms of the GNU General Public License as published by
  18. ;;; the Free Software Foundation; either version 2 of the License, or
  19. ;;; (at your option) any later version.
  20. ;;;
  21. ;;; This program is distributed in the hope that it will be useful,
  22. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. ;;; GNU General Public License for more details.
  25. ;;;
  26. ;;; You should have received a copy of the GNU General Public License
  27. ;;; along with this program; if not, write to the Free Software
  28. ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. ;;; Synched up with: Not in FSF.
  31.  
  32. ;;; Commentary:
  33.  
  34. ;;; NOTE: Apparently not being maintained by the author, who now
  35. ;;; uses jka-compr.el. --ben (1/26/96)
  36. ;;; Included patch (1/26/96)
  37.  
  38. ;;; Please see notes on INSTALLATION and USAGE on the pages below.
  39.  
  40. ;;; LCD Archive Entry:
  41. ;;; crypt++|Rod Whitby and Lawrence R. Dodd|dodd@roebling.poly.edu|
  42. ;;; Code for handling all sorts of compressed and encrypted files.|
  43. ;;; 1994/03/31 12:30:17|2.83|~/misc/crypt++.el.Z|
  44.  
  45. ;;; AVAILABLE: 
  46. ;;; 
  47. ;;; via anonymous ftp to roebling.poly.edu [128.238.5.31] in 
  48. ;;; /pub/lisp/crypt++.el.gz
  49. ;;; 
  50. ;;; via anonymous ftp to archive.cis.ohio-state.edu [128.146.8.52] in 
  51. ;;; /pub/gnu/emacs/elisp-archive/misc/crypt++.el.Z
  52.  
  53. ;;; BUG REPORTS
  54. ;;; 
  55. ;;; Type M-x crypt-submit-report to generate a bug report template or put your
  56. ;;; cursor at the end of this line and type C-x C-e: (crypt-submit-report)
  57. ;;; 
  58. ;;; Please note that this bug-report facility (crypt-submit-report) uses Barry
  59. ;;; Warsaw's reporter.el which is part of GNU Emacs v19 and bundled with many
  60. ;;; other packages.  If needed, you can obtain a copy of reporter.el at
  61. ;;; /roebling.poly.edu:/pub/reporter.el or the elisp-archive.  In fact,
  62. ;;; crypt-submit-report will attempt to ange-ftp a copy for you from roebling
  63. ;;; if you do not have one accessible.
  64.  
  65. ;;; Lawrence R. Dodd <dodd@roebling.poly.edu>
  66. ;;; Polytechnic University
  67. ;;; Brooklyn, New York USA
  68.  
  69. ;;; VERSION:
  70. ;;;  
  71. ;;; Version: 2.83
  72. ;;; Ident: crypt++.el,v 2.82 1994/03/31 12:30:17 dodd Exp
  73. ;;; Date: 1994/03/31 12:30:17
  74.  
  75.  
  76. ;;; INSTALLATION:
  77. ;;;
  78. ;;; To use this package, simply put it in a file called "crypt.el" in a Lisp
  79. ;;; directory known to Emacs (see `load-path'), byte-compile it (you may get a
  80. ;;; warning saying that the function reporter-submit-bug-report is not known
  81. ;;; to be defined -- ignore it), and put the line:
  82. ;;;
  83. ;;;                      (require 'crypt)
  84. ;;;
  85. ;;; in your ~/.emacs file or in the file default.el in the ../lisp directory
  86. ;;; of the Emacs distribution.  Do not bother trying to autoload this file;
  87. ;;; this package uses find-file and write-file hooks and thus should be loaded
  88. ;;; the first time you visit any sort of file.  Any package loaded after this
  89. ;;; one that appends something to `write-file-hooks' will not be executed
  90. ;;; because this package writes out the file.  Other packages that append to
  91. ;;; `write-file-hooks' should either be modified to prepend to that hook or be
  92. ;;; loaded before this one (preferably the former).
  93.  
  94. ;;; NOTE: encryption users should set `crypt-encryption-type' to one of the
  95. ;;; values in `crypt-encryption-alist' (see USAGE below).
  96.  
  97. ;;; SEE ALSO: /roebling.poly.edu:/pub/crypt++-fnf.el for file-not-found 
  98. ;;; support for GNU Emacs.
  99.  
  100. ;;; SPECIAL NOTES:
  101. ;;;  
  102. ;;; If crypt is dumped with the emacs executable, or if it has already been
  103. ;;; loaded in an emacs session, then modifying the variables used in building
  104. ;;; the encryption and encoding tables will have no effect until these tables
  105. ;;; are rebuilt.  This may be done with `M-x crypt-rebuild-tables'.  See USAGE
  106. ;;; below to determine variables for which this is needed.  For example,
  107. ;;; post-load changes to `crypt-encryption-file-extension' or
  108. ;;; `crypt-freeze-vs-fortran' can be incorporated into the encryption table
  109. ;;; via `M-x crypt-rebuild-tables'.  Similarly, post-load changes to
  110. ;;; `crypt-bind-insert-file' are handled with `M-x crypt-bind-insert-file'.
  111.  
  112.  
  113. ;;; USAGE:
  114. ;;; 
  115. ;;; By default, intended to be transparent.  User-defined variables 
  116. ;;; 
  117. ;;;     controlling ENCRYPTION are
  118. ;;;  
  119. ;;;        crypt-encryption-type
  120. ;;;        crypt-encryption-file-extension
  121. ;;;        crypt-never-ever-decrypt
  122. ;;;        crypt-auto-write-buffer-encrypted
  123. ;;;        crypt-confirm-password
  124. ;;;        crypt-encrypted-disable-auto-save
  125. ;;;        crypt-encryption-alist
  126. ;;;  
  127. ;;;     controlling ENCODING are
  128. ;;;  
  129. ;;;        crypt-auto-decode-buffer
  130. ;;;        crypt-auto-write-buffer
  131. ;;;        crypt-query-if-interactive
  132. ;;;        crypt-no-extension-implies-plain
  133. ;;;        crypt-freeze-vs-fortran
  134. ;;;        crypt-compact-vs-C++
  135. ;;;        crypt-ignored-filenames
  136. ;;;        crypt-default-encoding
  137. ;;;        crypt-encoded-disable-auto-save
  138. ;;;        crypt-encoding-alist
  139. ;;; 
  140. ;;;     controlling file insertion are
  141. ;;; 
  142. ;;;        crypt-bind-insert-file
  143. ;;;        crypt-auto-decode-insert
  144. ;;;      
  145. ;;; To find out more about these variables, load this file, put your cursor at 
  146. ;;; the end of any of the variable names, and hit C-h v [RET].
  147. ;;;  
  148. ;;; NOTE: encryption users should set `crypt-encryption-type' to one of the
  149. ;;; values in `crypt-encryption-alist'
  150. ;;;
  151. ;;; Although rarely needed, the following functions may be called interactively
  152. ;;;
  153. ;;;        (crypt-encoded-mode)
  154. ;;;        (crypt-encode-region)
  155. ;;;        (crypt-encrypted-mode)
  156. ;;;        (crypt-encrypt-region)
  157. ;;;        (crypt-set-encryption-key)
  158. ;;;        (crypt-rebuild-tables)
  159. ;;;        (crypt-insert-file)
  160. ;;;        (crypt-bind-insert-file)
  161. ;;;        (crypt-submit-report)
  162. ;;;
  163. ;;; To find out more about these functions, load this file, put your cursor
  164. ;;; inside any of the `()' of the above lines, and hit C-h f [RET].
  165.  
  166.  
  167. ;;; NOTES ON INTERFACES WITH OTHER PROGRAMS AND PACKAGES:
  168. ;;;
  169. ;;; GZIP: the environment variable GZIP of gzip can cause an error if it
  170. ;;; contains `--verbose' because standard output messages will be appended to
  171. ;;; gzip'ed files.  This corrupts the files.  The cleanest solution is to pass
  172. ;;; the `--quiet' switch in `crypt-encoding-alist' to override this.  use gzip
  173. ;;; version 1.0.4 or higher from prep.ai.mit.edu:/pub/gnu
  174. ;;; 
  175. ;;; TAR-MODE: works properly with version 1.28 (or higher) with v19 emacs.
  176.  
  177.  
  178. ;;; DESCRIPTION:
  179. ;;;
  180. ;;; The basic purpose of this package of Lisp functions is to recognize
  181. ;;; automatically encrypted and encoded (i.e., compressed) files when they are
  182. ;;; first visited or written.  The BUFFER corresponding to the file is decoded
  183. ;;; and/or decrypted before it is presented to the user.  The file itself is
  184. ;;; unchanged on the disk.  When the buffer is subsequently saved to disk, a
  185. ;;; hook function re-encodes the buffer before the actual disk write takes
  186. ;;; place.
  187. ;;;
  188. ;;; This package recognizes all sorts of compressed files by a magic number at
  189. ;;; the beginning of these files but uses a heuristic to detect encrypted
  190. ;;; files.  If you are asked for an encryption key for a file that is in fact
  191. ;;; not encrypted, just hit RET and the file will be accepted as is, and the
  192. ;;; crypt minor mode will not be entered.
  193. ;;;
  194. ;;; Other types of encoding programs may be added to this package by using the
  195. ;;; variable `crypt-encoding-alist' which contains a table of encoding
  196. ;;; programs such as compress, gzip (GNU zip), freeze, and compact.
  197. ;;;
  198. ;;; This new extended version of crypt now monitors the filename extensions of
  199. ;;; buffers that are written out using write-file (C-x C-w).  If the filename
  200. ;;; extension matches one of the extensions listed in `crypt-encoding-alist,'
  201. ;;; then this package will write the file out using the corresponding encoding
  202. ;;; (compression) method. This is done whether or not the buffer originated
  203. ;;; from a previously encoded (compressed) file.
  204. ;;;
  205. ;;; Thus, if the user is editing a file that may or may not have been encoded
  206. ;;; originally (e.g., foobar.Z or foobar) and decides to write it to a
  207. ;;; different file (e.g., barfoo or barfoo.z or barfoo.C).  This package will
  208. ;;; examine the filename extension and write the buffer in plain format or an
  209. ;;; alternate encoding (compression) format by searching through the entries
  210. ;;; in the table of encoding methods `crypt-encoding-alist.'  This change in
  211. ;;; encoding state is done automatically if the variable
  212. ;;; `crypt-auto-write-buffer' is t otherwise the user is asked.
  213.  
  214.  
  215. ;;; TO DO/KNOWN BUGS/HELP WANTED/APPLY WITHIN: 
  216. ;;; 
  217. ;;; All Users/hackers out there are strongly encouraged to pursue any of these
  218. ;;; matters further (especially those that concern encryption and decryption!).
  219. ;;; It is important to future programmers and modifiers of crypt++.el to know
  220. ;;; about its perceived limitations.  Since necessity drives invention, users
  221. ;;; who find any of the following features of crypt++.el annoying are asked to
  222. ;;; make suggestions and send patches (again, especially those that concern
  223. ;;; encryption and decryption!).
  224. ;;; 
  225. ;;; * currently crypt++ assumes that if a file is both encrypted and encoded
  226. ;;;   (i.e., compressed) that the order in which it was done was encryption
  227. ;;;   first _then_ compression.  As has been pointed by many people compression
  228. ;;;   following encryption is useless since the encrypted file is basically
  229. ;;;   random.  On the other hand, many agree that doing encryption _following_
  230. ;;;   compression is better since it makes it harder to crack the encryption.
  231. ;;;   We would like to make the ordering of these two user-configurable or if
  232. ;;;   nothing else change the order.
  233. ;;; 
  234. ;;;   Having read the above however, Francois Pinard <pinard@iro.umontreal.ca> 
  235. ;;;   writes that encryption following compression may not be harder to crack 
  236. ;;;   since "the fact that the first few uncrypted bytes are expected (the 
  237. ;;;   compress signature) facilitates a serious attempt at uncrypting." 
  238. ;;;   jwz agrees with Francois.
  239. ;;; 
  240. ;;; * get write-region and append-to-file to handle encoded and encrypted
  241. ;;;   files.  There is an interesting low-level encoding package by Jay Adams
  242. ;;;   <jka@ece.cmu.edu> called jka-compr.el that might address some of these
  243. ;;;   issues.  We encourage hackers out there to come up with crypt++ versions
  244. ;;;   of write-region and append-to-file.  The difficulty is creating versions
  245. ;;;   that mimic the originals as closely as possible.
  246. ;;;
  247. ;;; * instead of using call-process-region (which can fail badly if the region 
  248. ;;;   is large and there's not much room in /tmp), write the region to a temp 
  249. ;;;   file (with a customisable location) and use call-process directly.
  250. ;;;
  251. ;;; * users have mentioned trouble using crypt++ and hilit simultaneously since 
  252. ;;;   the functions in write-file-hook for both write the file to disk and
  253. ;;;   return t.  A possible solution is to have one of them write to a
  254. ;;;   scratch buffer instead of to disk and return nil and then allow the
  255. ;;;   other to do its work on the scratch buffer and write it to disk.  Thanks
  256. ;;;   to Wayne Folta <folta@cs.UMD.EDU> and Amir J Katz <amir@matis.ingr.com>.
  257. ;;;   It would be nice to have another way in emacs to have an
  258. ;;;   after-write-file-hook and a before-write-file-hook of some sort.
  259. ;;;   Lucid Emacs has an after-write-file-hook.  Recent versions of hilit19.el 
  260. ;;;   do not automatically attach to `write-file-hooks' and return t. 
  261. ;;;   However, the general problem of multiple packages returning t still 
  262. ;;;   remains.  dos-mode.el and crypt.el also conflict.
  263. ;;;  
  264. ;;; * another possible source of trouble is with encryption (and encoding) 
  265. ;;;   programs sticking verbose output into buffers prior to being written to
  266. ;;;   disk.  This was definitely occurring with gzip because of --verbose in
  267. ;;;   the GZIP environment variable and is solved/hidden with the --quiet
  268. ;;;   switch.  However, I suspect that some encryption problems out there are
  269. ;;;   capable of similar things so the user should be careful.
  270. ;;; 
  271. ;;; * integrating crypt++ with a backgrounding package such as Olin Shivers' 
  272. ;;;   `background.el' might be useful too.  thanks to Mark Borges 
  273. ;;;   <mdb@noaacrd.Colorado.EDU> for suggesting this.
  274. ;;; 
  275. ;;; * Performing M-x crypt-encode-buffer or M-x crypt-encrypt-buffer and then
  276. ;;;   saving the file would possibly cause errors.  It is better to toggle
  277. ;;;   `crypt-encoded-mode' (or `crypt-encrypted-mode') and simply save the
  278. ;;;   file.  It is for this reason that `crypt-encode-buffer' and
  279. ;;;   `crypt-encrypt-buffer' are not interactive.
  280. ;;; 
  281. ;;; * use plists instead of alists replacing calls to `nth' with `get' 
  282. ;;; 
  283. ;;; * merge encryption code completely into encoding code making encryption
  284. ;;;   just a special case of encoding.
  285.  
  286.  
  287. ;;; Change log:
  288. ;;;  
  289. ;;; 1.1 - original version of crypt.el
  290. ;;; 1.2 -
  291. ;;;   jwz: works with tar-mode.el
  292. ;;;   jwz: applied patch from piet, merged with Lawrence Dodd's gzip version
  293. ;;; 1.3 -
  294. ;;;   lrd: fixed compress-magic-regexp 
  295. ;;; 1.4, 1.5, 1.6 -
  296. ;;;   lrd: write-file compresses or gzips based on file extension
  297. ;;; 2.1 -
  298. ;;;   lrd: merged with Rod Whitby's table-driven version (major upgrade)
  299. ;;; 2.2 -
  300. ;;;   rjw: Changed file name to crypt++.el, so archie and lispdir can find it.
  301. ;;; 2.3 -
  302. ;;;   rjw: Separated the hook additions and minor mode alist additions.
  303. ;;; 2.4 -
  304. ;;;   rjw: Fixed the interactive form for crypt-buffer.
  305. ;;; 2.5 - 
  306. ;;;   lrd: doc mods, changed GNU free software notice (was out of date), added 
  307. ;;;   anonymous ftp information
  308. ;;; 2.6 - 
  309. ;;;   lrd: added back in definition of `buffer' in defun crypt-buffer caused 
  310. ;;;   an error when trying to read encrypted file; modified check for minor 
  311. ;;;   mode alist addition; added gzip magic number warning
  312. ;;; 2.7 - [posted to gnu.emacs.sources]
  313. ;;;   lrd: added `TO DO' and `KNOW BUGS' section to header 
  314. ;;; 2.8 - 
  315. ;;;   lrd: added note about updating to v 1.24 of tar-mode.el
  316. ;;;   Thanks to Mark Borges <mdb@noaacrd.Colorado.EDU>
  317. ;;; 2.9 -
  318. ;;;   lrd: moved query about `crypt-freeze-vs-fortran' out of defvar for
  319. ;;;   `crypt-encoding-alist,' an erroneous value of nil was being stuck into
  320. ;;;   alist when user set `crypt-freeze-vs-fortran' was nil, doc mod.
  321. ;;;   Thanks to Mark Borges <mdb@noaacrd.Colorado.EDU>
  322. ;;; 2.10 -
  323. ;;;   rjw: moved query about `crypt-freeze-vs-fortran' back into defvar for
  324. ;;;   `crypt-encoding-alist,' - used append to ignore the erroneous nil.
  325. ;;; 2.11 -
  326. ;;;   rjw: fixed a bug in my fix :-(
  327. ;;; 2.12 -
  328. ;;;   rjw: Defvar crypt-magic-regexp and crypt-magic-regexp-inverse and
  329. ;;;   allow either a regexp or an elisp expression.
  330. ;;;   Suggested by Franc,ois Pinard <pinard@iro.umontreal.ca>.
  331. ;;; 2.13 - 
  332. ;;;   lrd: added in info on lispdir.el, doc mods and some puttering while 
  333. ;;;   looking over rjw's v 2.12 mods.
  334. ;;; 2.14 - 
  335. ;;;   lrd: doc mod - trivial huh? switched `compact' and  `gzip' in 
  336. ;;;   `crypt-encoding-alist' - want gzip near top
  337. ;;; 2.15 - 
  338. ;;;   lrd: added in LCD Archive Entry and modified comments on tar-mode.el 
  339. ;;;   since the version at the elisp-archive now works with crypt++.el
  340. ;;; 2.16 - 
  341. ;;;   lrd: provide `crypt' as well as `crypt++' allowing something like `ln -s 
  342. ;;;   crypt++.el crypt.el' to be meaningful 
  343. ;;;   Suggested (by|as) Per Abrahamsen <amanda@iesd.auc.dk>
  344. ;;; 2.17 -
  345. ;;;   lrd: clarified bug report procedure, added fancy pseudo-graphics, added 
  346. ;;;   to the `TO DO' list, put RCS tags in LCD Archive entry
  347. ;;; 2.18 - [posted to gnu.emacs.sources]
  348. ;;;   lrd: included pointer to elisp archive in crypt-version description,
  349. ;;;   changed "Decode buffer %s? " to "Decode %s? " in crypt-find-file-hook 
  350. ;;;   to be more general (mainly for crypt-insert-file)
  351. ;;; 2.19 -
  352. ;;;   rjw: Added the crypt-compact-vs-C++ switch to distinguish compacted and
  353. ;;;   C++ files.
  354. ;;; 2.20 -
  355. ;;;   lrd: (1) modified interactive form of crypt-buffer. (2) made search 
  356. ;;;   case-insensitive in crypt-submit-report. (3) modified encoded-mode and 
  357. ;;;   crypt-mode so that buffer-modified is not unconditionally set to nil 
  358. ;;;   when the mode is not changed. Thanks to Gerd Hillebrand 
  359. ;;;   <ggh@cs.brown.edu> for suggesting (2) and (3).
  360. ;;; 2.21 -
  361. ;;;   rjw: Added an entry to the TODO list about the hazards of using
  362. ;;;   call-process-region on a large region and not much room in /tmp
  363. ;;;   (David Carlisle <carlisle@computer-science.manchester.ac.uk>).
  364. ;;; 2.22 - 
  365. ;;;   lrd: allow write-file-hooks to contain functions as well as lists. 
  366. ;;;   Contributed by Ken Laprade <laprade@trantor.harris-atd.com>.
  367. ;;; 2.23 - 
  368. ;;;   lrd: made crypt-submit-report list values of more user-defined variables
  369. ;;; 2.24 - 
  370. ;;;   lrd: pass the -q switch to gzip to thwart the possibility of a --verbose
  371. ;;;   in the GZIP environment variable
  372. ;;; 2.25 -
  373. ;;;   lrd: added some more to the TO DO list, clarified some things, also 
  374. ;;;   untabified the entire file (I got tired of the control I's) 
  375. ;;; 2.26 - 
  376. ;;;   lrd: use the long-named options for GNU zip (self-documenting)
  377. ;;; 2.27 - 
  378. ;;;   lrd: included observation by Francois Pinard <pinard@iro.umontreal.ca> 
  379. ;;;   and worked on text in TO DO/KNOWN BUGS list
  380. ;;; 2.28 - 
  381. ;;;   lrd: added two new variables in (crypt-submit-report) to the list stuck
  382. ;;;   at the bottom of the mail message; changed the comments regarding the 
  383. ;;;   user-defined variables.  added in default values in user defined 
  384. ;;;   variables.  added to and removed stuff to the `TO DO' list.
  385. ;;;
  386. ;;;   (encoded-mode): 
  387. ;;;   added in code to remove any auto-save-files that may have been formed
  388. ;;;   before becoming an encoded buffer (for example a plain file saved to
  389. ;;;   disk encoded had orphan auto-save-files left behind).  turning off
  390. ;;;   auto-save-mode disables the creation of auto-save-files, but it also 
  391. ;;;   disables the possibility of these being removed when the buffer is 
  392. ;;;   saved.
  393. ;;; 
  394. ;;;   (crypt-region): 
  395. ;;;   now call the encryption and decryption program directly instead of
  396. ;;;   through the shell.  this is more secure since the shell will expose the
  397. ;;;   password (key).  thanks to Jon Cargille <jcargill@cs.wisc.edu>.  defined
  398. ;;;   two new variables `crypt-decryption-args' and `crypt-encryption-args' to
  399. ;;;   take the arguments separately.  removed (let ((opoint)...)) construct 
  400. ;;;   this was a throw back to some old dead code and was not being used.
  401. ;;; 2.29 - 
  402. ;;;   lrd: added three new variables in (crypt-submit-report); added to the 
  403. ;;;   `TO DO' list.
  404. ;;;  
  405. ;;;   (encode-region,encode-buffer,encoded-mode): fixed interactive forms -
  406. ;;;   the conversion to table version had eliminated some of the interactive
  407. ;;;   features of these.  thanks to Kimball Collins <kpc@ptolemy.arc.nasa.gov>
  408. ;;;   for point this out.  new interactive form uses functions
  409. ;;;   `crypt-get-encoding-type' and `crypt-symbol-alist-to-table' and variable
  410. ;;;   `crypt-default-encoding' to generate completion list of encoding types.
  411. ;;; 
  412. ;;;   (crypt-write-file-hook): two new user-defined variables
  413. ;;;   `crypt-query-if-interactive' and `crypt-no-extension-implies-plain' and
  414. ;;;   the buffer-local variable `buffer-interactive-mode' are used to help
  415. ;;;   determined whether or not plain output is really desired for files
  416. ;;;   without a compression file-name extension.  the default behavior is the
  417. ;;;   same as before.
  418. ;;; 2.30 - 
  419. ;;;   lrd: added test for user-defined variable `crypt-never-ever-decrypt' 
  420. ;;;   when finding a file.  some users may never wish to decrypt files 
  421. ;;;   and like to edit binary files.  thanks to Nelson Minar 
  422. ;;;   <nelson@reed.edu>.  added to doc-strings of 
  423. ;;;   `crypt-magic-regexp[-inverse]' -- these can be set to nil[t] and 
  424. ;;;   accomplish the same thing as setting `crypt-never-ever-decrypt' to t
  425. ;;; 2.31 - 
  426. ;;;   rjw: Updated the comments in the encryption check section.
  427. ;;; 2.32 - [posted to gnu.emacs.sources]
  428. ;;;   lrd: added warning about `crypt-(de|en)cryption-program'; doc mod.
  429. ;;; 2.33 - 
  430. ;;;   lrd: if `crypt-(de|en)cryption-args' are nil then don't pass any
  431. ;;;   arguments to (de|en)cryption program, nil is the default instead of
  432. ;;;   "".  Thanks to Joe Ilacqua <spike@world.std.com>, David J. Schur
  433. ;;;   <djs@idm.com>, Peter Nuth <nuth@ai.mit.edu>, and Greg Larson 
  434. ;;;   <glarson@bnr.ca>.  `-q' exists in gzip 1.0.3 but not `--quiet' changed 
  435. ;;;   GZIP NOTE.  Thanks to Chris Moore <moore@src.bae.co.uk>.
  436. ;;; 2.34 - 
  437. ;;;   lrd: allow `crypt-(de|en)cryption-args' to be a list of strings -- more
  438. ;;;   robust.  query for password (key), if none is set, when writing out file
  439. ;;;   for which `buffer-save-encrypted' is t.  Thanks to John Interrante
  440. ;;;   <interran@uluru.Stanford.EDU>.  (crypt-write-file-hook): check filename
  441. ;;;   extension against regexp `crypt-encryption-file-extension' and query for
  442. ;;;   encryption, unless `crypt-auto-write-buffer-encrypted' is t (don't
  443. ;;;   bother doing reverse check, encrypted to plain, not a common request).
  444. ;;;   (crypt-mode): delete auto-save files (cf., encoded-mode), may exist now.
  445. ;;;   (read-string-no-echo): applied patch from Piet van Oostrum
  446. ;;;   <piet@cs.ruu.nl> -- set `cursor-in-echo-area' _after_ setting buffer
  447. ;;;   (this was screwing up gnews).
  448. ;;; 2.35 - 
  449. ;;;   lrd: doc mod
  450. ;;; 2.36 - 
  451. ;;;   lrd: fixed typo, added RMAIL note.
  452. ;;; 2.37 - [posted to gnu.emacs.sources]
  453. ;;;   lrd: 
  454. ;;;   (crypt-write-file-hook): search user-defined list
  455. ;;;   `crypt-ignored-filenames' for possible match with `buffer-filename'
  456. ;;;   before attempting conversion from compressed to plain format; useful for
  457. ;;;   compressed incoming mail files (e.g., RMAIL, INBOX).
  458. ;;;  
  459. ;;;   (crypt-mode): query for key if not set already; need to switch order of
  460. ;;;   recovering key and toggling crypt-mode in crypt-find-file-hook (thanks
  461. ;;;   to Piet van Oostrum <piet@cs.ruu.nl>).
  462. ;;;  
  463. ;;;   (crypt-buffer) and (encode-buffer): remove interactive form; use
  464. ;;;   (crypt-mode) and (encoded-mode) instead so encryption and compression
  465. ;;;   are done at the very end; leave interactive form in (crypt-region) and
  466. ;;;   (encode-region) may still be used.
  467. ;;;  
  468. ;;;   (set-encryption-key): remove from `command-history' if called
  469. ;;;   interactively - thanks to George M. Georgiou
  470. ;;;   <georgiou@silicon.csci.csusb.edu>.
  471. ;;; 2.38 - 
  472. ;;;   lrd: added `crypt-' prefix to `(read-string-no-echo)' and `(save-point)'
  473. ;;;   changed file extension for gzip files to `.z' _or_ `.gz' (future release
  474. ;;;   of gzip with use later extension by default and so this should be
  475. ;;;   changed to just `.gz' someday).
  476. ;;; 2.39 - 
  477. ;;;   lrd: doc mod. added in patch from jwz - `(crypt-read-string-no-echo)' is
  478. ;;;   more secure, put property 'permanent-local on buffer-locals works for
  479. ;;;   Lucid Emacs and doesn't harm v18 emacs, change `buffer-interactive-mode'
  480. ;;;   to `buffer-interactive-encoded-mode.'
  481. ;;; 2.40 - 
  482. ;;;   lrd: put property 'preserved in case kill-fix.el is being used.
  483. ;;; 2.41 - 
  484. ;;;   lrd: all functions and variables now start with `crypt-', moved REVISION
  485. ;;;   HISTORY to bottom of header, interactive version of
  486. ;;;   `(crypt-encrypt-region)' clearer, `(crypt-read-string-no-echo)' now
  487. ;;;   echos `.'
  488. ;;; 2.42 -
  489. ;;;   lrd: (crypt-check-extension-for-encoding): broke out of
  490. ;;;   `(crypt-write-file-hook)'.  setting user variables
  491. ;;;   `crypt-compact-vs-C++' and `crypt-freeze-vs-fortran' to nil no longer
  492. ;;;   completely disables the reading compact'ed and frozen files but just
  493. ;;;   disables the use of the file-extension tricks of
  494. ;;;   `(crypt-check-extension-for-encoding).'  (crypt-encode-region): allow
  495. ;;;   for a single line message from encoding program at top of region; if it
  496. ;;;   is there, then remove it; kludge for `compact' program.
  497. ;;; 2.43 - 
  498. ;;;   lrd: (crypt-encode-region): generalize the clean up procedure; add
  499. ;;;   element to `crypt-encoding-alist' and introduce new function
  500. ;;;   `(crypt-encoding-cleanup-regexp)' to extract a compression specific
  501. ;;;   regexp for erroneous message or lisp expression for cleanup.
  502. ;;; 2.44 - 
  503. ;;;   lrd: new element for `crypt-encoding-alist' handles whether or not
  504. ;;;   file-name extension tricks may be play with encoding method; compact and
  505. ;;;   freeze values default to `crypt-compact-vs-C++' and
  506. ;;;   `crypt-freeze-vs-fortran' (thanks to rjw);
  507. ;;;   (crypt-encoding-extension-tricks): new defun to handle this;
  508. ;;;   (crypt-check-extension-for-encoding): monitors "tricks" entry of
  509. ;;;   `crypt-encoding-alist' and adjust the bag of tricks it can apply.
  510. ;;; 2.45 - 
  511. ;;;   lrd: (crypt-encode-region): delete entire match of cleanup regexp by
  512. ;;;   requiring newlines in GARBAGE-REGEXP-OR-LISPEXP.  (crypt-submit-report):
  513. ;;;   use Warsaw's reporter.el.
  514. ;;; 2.46 -
  515. ;;;   lrd: (crypt-find-file-hook, crypt-write-file-hook): cleaned, documented,
  516. ;;;   and replaced occurrences of `(cond (C BODY))' with `(if C BODY)';
  517. ;;;   changed `crypt-magic-regexp' to `crypt-encryption-magic-regexp' and
  518. ;;;   `crypt-magic-regexp-inverse' to `crypt-encryption-magic-regexp-inverse'
  519. ;;;   for consistency with other variable names. new user-defined variable
  520. ;;;   `crypt-encryption-minor-mode-name' instead of always "Crypt".  grouped
  521. ;;;   all encryption variables together.
  522. ;;; 2.47 - 
  523. ;;;   lrd: somewhat major change - put program-specific encryption variables
  524. ;;;   into a single table `crypt-encryption-alist' and let the variable
  525. ;;;   `crypt-encryption-type' define the appropriate entry to use; new
  526. ;;;   user-defined variable `crypt-confirm-password,' thanks to Jeff Clark
  527. ;;;   <jclark@src.honeywell.com>. (crypt-submit-report): improved error 
  528. ;;;   handling, thanks to baw. (crypt-write-file-hook): fixed bug with 
  529. ;;;   `crypt-encoding-extension-tricks'
  530. ;;; 2.48 - 
  531. ;;;   lrd: added dummy argument to `crypt-encoding-alist' and
  532. ;;;   `crypt-encryption-alist' and merged all defuns that work on their
  533. ;;;   elements into defuns that all start with `crypt-get-' and look through
  534. ;;;   both lists.  simplifies some of code and closer to treating encryption
  535. ;;;   as a special case of encoding; crypt-minor-mode-alist: replaced (nth *)
  536. ;;;   with `(crypt-get-minor-mode)' call; (crypt-encode-region): allow
  537. ;;;   arguments to be list of strings; renamed (crypt-get-encoding-type) to
  538. ;;;   (crypt-read-encoding-type) for clarity.
  539. ;;; 2.49 - [posted to gnu.emacs.sources]
  540. ;;;   lrd: (crypt-encode-region): ignore `args' if set to t
  541. ;;; 2.50 - 
  542. ;;;   lrd: (crypt-write-file-hook): in v19 we need to call `backup-buffer'
  543. ;;;   ourselves -- we write out the file and return t so `basic-save-buffer'
  544. ;;;   does not do it; also call `set-file-modes'
  545. ;;; 2.51 -
  546. ;;;   lrd: some `defvar's are now `defconst's and tar-mode note was changed.
  547. ;;; 2.52 - 
  548. ;;;   lrd: make doc strings conform to GNU standards.
  549. ;;; 2.53 - 
  550. ;;;   lrd: made header conform to GNU Conventional Headers standard.
  551. ;;; 2.54 -
  552. ;;;   lrd: `crypt-encryption-file-extension', `crypt-freeze-vs-fortran',
  553. ;;;   `crypt-compact-vs-C++', `crypt-encryption-magic-regexp', and
  554. ;;;   `crypt-encryption-magic-regexp-inverse' are used in defining the tables
  555. ;;;   `crypt-encoding-alist' and `crypt-encryption-alist' and so need to be set
  556. ;;;   _before_ loading crypt++.  use `add-hook' if it is available.
  557. ;;; 2.55 - 
  558. ;;;   lrd: new interactive function `crypt-insert-file' mimics `insert-file' 
  559. ;;;   but attempts to decode or decrypt before insertion; bound `C-x i' if
  560. ;;;   `crypt-bind-insert-file' is non-nil.  comment out doc-strings from 
  561. ;;;   internal subroutines, saves space.
  562. ;;; 2.56 -
  563. ;;;   tfb: change the definitions of crypt-{encoding,encryption}-alist, to
  564. ;;;   call the functions crypt-make-{encoding,encryption}-alist resp.
  565. ;;;   Added crypt-reinit which regenerates these variables from their
  566. ;;;   functions, thus allowing this stuff to be preloaded even if people
  567. ;;;   set things in their init files.
  568. ;;;   Tim Bradshaw <tim.bradshaw@mid-heidelberg.de> 
  569. ;;; 2.57 - 
  570. ;;;   lrd: untabify; remove duplicate entry in `crypt-make-encoding-alist';
  571. ;;;   change name of `crypt-make-*-alist' to `crypt-build-*-alist' and
  572. ;;;   `crypt-reinit' to `crypt-rebuild-tables'; (crypt-read-string-no-echo):
  573. ;;;   change local variable `form' to `help-form' so it is defined;
  574. ;;;   `crypt-encryption-alist' and `crypt-encoding-alist' must be defined with
  575. ;;;   `defconst' since we wish crypt++ to initialize these variables
  576. ;;;   unconditionally; modify INSTALLATION section to reflect these changes.
  577. ;;; 2.58 - 
  578. ;;;   lrd: doc mod.
  579. ;;; 2.59 - [posted to gnu.emacs.sources]
  580. ;;;   lrd: (crypt-bind-insert-file): new function for changing "C-x i" in 
  581. ;;;   initialization file or interactively.
  582. ;;; 2.60 - 
  583. ;;;   lrd: add `crypt-rebuild-tables' and `crypt-bind-insert-file' to 
  584. ;;;   `after-init-hook' in GNU emacs v19 and to `term-setup-hook' in Lucid 
  585. ;;;   emacs.  Change INSTALLATION notes.
  586. ;;; 2.61 - [posted to gnu.emacs.sources]
  587. ;;;   lrd: Doc mod.  Clean up the installation of minor mode indicators.
  588. ;;; 2.62 - [posted to gnu.emacs.sources]
  589. ;;;   lrd: installed patch from stig@hackvan.com to simplify crypt-get-* defuns
  590. ;;;   (now defmacros).  Don't add to `term-setup-hook' unless no
  591. ;;;   `after-init-hook' _and_ definitely running v19, otherwise Rod gets an 
  592. ;;;   error at home :-<.  Don't assume C-x i had `insert-file' bound to it: 
  593. ;;;   store old binding in `crypt-old-binding' before overwriting and use in 
  594. ;;;   function `crypt-bind-insert-file.'
  595. ;;; 2.63 - 
  596. ;;;   lrd: (crypt-encode-buffer, crypt-encode-region, crypt-encrypt-buffer,
  597. ;;;   crypt-encrypt-region): changed argument list putting optional buffer
  598. ;;;   last and making default action to encode or encrypt. (crypt-encoded-p,
  599. ;;;   crypt-encrypted-p): new functions that do the actual testing of file
  600. ;;;   contents.  (crypt-find-file): uses these new functions.
  601. ;;;   (crypt-rebuild-minor-modes-alist): new function to rebuild
  602. ;;;   `minor-mode-alist' called by function crypt-rebuild-tables.
  603. ;;;   (crypt-build-minor-mode-alist): new function called by
  604. ;;;   `crypt-minor-mode-alist' to create itself.  `crypt-minor-mode-encrypted'
  605. ;;;   removed because defined in function crypt-build-minor-mode-alist.
  606. ;;; 2.64 - 
  607. ;;;   lrd: (crypt-find-file-hook): temporarily remove the encrytion file
  608. ;;;   extension to help determine the major mode, just like is done with the
  609. ;;;   encoding file extension.  In order for this to work properly the file
  610. ;;;   extension in `crypt-encryption-file-extension' and
  611. ;;;   `crypt-encryption-alist' needs to be inside a pair of \\( \\).
  612. ;;; 2.65 - 
  613. ;;;   lrd: (crypt-find-file-hook): move determination of key, password, into
  614. ;;;   (crypt-encrypted-p).
  615. ;;; 2.66 - 
  616. ;;;   lrd: (crypt-set-encryption-key): improve prompt string for encryption 
  617. ;;;   key.
  618. ;;; 2.67 - 
  619. ;;;   lrd: (crypt-write-file-hook): make check for encryption file-name 
  620. ;;;   extension case-sensitive.
  621. ;;; 2.68 - 
  622. ;;;   lrd: fixed check for previous addition to `minor-mode-alist' -- was not
  623. ;;;   working. Check for an `add-hook' function; if one does not exist then
  624. ;;;   use a copy of one from GNU Emacs 19.  When using `add-hook' to append to
  625. ;;;   the `write-file-hooks' make sure that the version accepts the optional
  626. ;;;   APPEND argument -- v19's does but the one in the elisp archive by Dan
  627. ;;;   LaLiberte <liberte@cs.uiuc.edu> does not append.  This causes problems.
  628. ;;;   Thanks to Francesco Potorti` <pot@fly.CNUCE.CNR.IT> for pointing this
  629. ;;;   out.
  630. ;;; 2.69 - [posted to gnu.emacs.sources]
  631. ;;;   lrd: doc mod with regards `after-init-hook' and Lucid Emacs.  Add 
  632. ;;;   pointer to crypt++-fnf.el for people who might be interested.
  633. ;;; 2.70 -
  634. ;;;   lrd: narrow conditions under which crypt-encryption-magic-regexp
  635. ;;;   matches.  Thanks to Philippe Michel <michel@thomson-lcr.fr> and Francois
  636. ;;;   Pinard <pinard@iro.umontreal.ca> for helping explain this with regards 
  637. ;;;   to ISO/Latin-1.
  638. ;;; 2.71 -
  639. ;;;   lrd: applied patches from Darrin Jewell <jewell@bdi.com> for DOS to UNIX
  640. ;;;   support.  DOS entry added to crypt-build-encoding-alist.
  641. ;;;   (crypt-dos-to-unix-region, crypt-unix-to-dos-region): New
  642. ;;;   functions. (crypt-dos-has-ctrl-z): New buffer-local variable.
  643. ;;;   (crypt-encode-region): allow for encoding and decoding programs to be
  644. ;;;   elisp expressions.  If they are then apply them directly to region.
  645. ;;;   Point out that crypt++.el conflicts with dos-mode.el.
  646. ;;; 2.72 - 
  647. ;;;   lrd: The limit for the regular expression search done by
  648. ;;;   `crypt-encrypted-p' is extended to 100 by default.  The enlargement of
  649. ;;;   search field is needed because of previous reduction in size of regexp
  650. ;;;   being searched for.  (crypt-magic-search-limit): New variable defining
  651. ;;;   this new limit.  (crypt-encrypted-p): Uses it and cleaned up.  Doc mod.
  652. ;;;   Thanks to Philippe Michel <michel@thomson-lcr.fr>, Francois Pinard
  653. ;;;   <pinard@iro.umontreal.ca>, and Dave Goldberg <dsg@blackbird.mitre.org>.
  654. ;;; 2.73 - [posted to gnu.emacs.sources]
  655. ;;;   lrd: Apply patch from Kevin Rodgers <kevin@traffic.den.mmc.com> that
  656. ;;;   uses more verbose messages and capitals.  Doc mod.
  657. ;;; 2.74 - 
  658. ;;;   lrd: Untabify.  (crypt-encrypted-p): Check value of
  659. ;;;   `crypt-never-ever-decrypt' before anything else.
  660. ;;; 2.75 - 
  661. ;;;   lrd: (crypt-version): Remove call to `substring'.
  662. ;;; 2.76 - 
  663. ;;;   lrd: (crypt-encryption-magic-regexp-inverse): Add in regexp that will
  664. ;;;   match ksh `.sh_history' files so that they are not interpreted as
  665. ;;;   encrypted files.  Thanks to Francesco Potorti` <pot@fly.CNUCE.CNR.IT>.
  666. ;;; 2.77 - [posted to gnu.emacs.sources]
  667. ;;;   lrd: (crypt-bind-insert-file): Use substitute-key-definition to bind
  668. ;;;   crypt-insert-file to whatever key insert-file is bound to (not
  669. ;;;   necessarily C-x i).  Call crypt-bind-insert-file directly in
  670. ;;;   file. Variable crypt-bind-insert-file: Doc mod.  Remove
  671. ;;;   crypt-old-binding.  Replace `M-x foobar' in doc strings with
  672. ;;;   `\\[foobar]'.
  673. ;;; 2.78 - 
  674. ;;;   lrd: (crypt-auto-write-answer-local): New internal variable.  Holds
  675. ;;;   answer to query about file-extension tricks question per buffer.  Thanks
  676. ;;;   to George Forman <forman@cs.washington.edu>.  Remove Rod from list of
  677. ;;;   maintainers...he's busy enough.  Merge multiple setq forms into single
  678. ;;;   setq forms.
  679. ;;; 2.79 -
  680. ;;;   lrd: (crypt-y-or-n-p): New internal function for querying.  Tests the
  681. ;;;   internal variable crypt-auto-write-answer-local to ensure single query.
  682. ;;;   (crypt-check-extension-for-encoding): Replace all occurrences of queries
  683. ;;;   involving y-or-no-p constructs with crypt-y-or-n-p.
  684. ;;; 2.80 - [posted to gnu.emacs.sources]
  685. ;;;   lrd: (crypt-set-encryption-key): Shorten interactive prompt.  Change
  686. ;;;   documentation.
  687. ;;; 2.81 - 
  688. ;;;   lrd: (crypt-variable-list): Add shell and path variables.
  689. ;;;   (crypt-confirm-password): Fix spelling error in doc.
  690. ;;; 2.82 - 
  691. ;;;   lrd: Applied patch from Noah Friedman <friedman@prep.ai.mit.edu>. 
  692. ;;;   (crypt-encoded-disable-auto-save, crypt-encrypted-disable-auto-save):
  693. ;;;   New user-defined variables. (crypt-encoded-mode, crypt-encrypted-mode):
  694. ;;;   Use them.
  695. ;;; 2.83 -
  696. ;;;   hniksic: Added custom.
  697.  
  698.  
  699. ;;; Code:
  700.  
  701. ;;;; User definable variables.
  702.  
  703. (progn
  704.   (defgroup crypt nil
  705.     "Handling compressed and encrypted files."
  706.     :group 'compression)
  707.   )
  708.  
  709. (defcustom crypt-encryption-type 'crypt
  710.   "*Method of encryption.  Must be an element of `crypt-encryption-alist.'
  711. If you change this after crypt++ is loaded then do \\[crypt-rebuild-tables]."
  712.   :type 'symbol
  713.   :group 'crypt)
  714.  
  715. (defcustom crypt-encryption-file-extension nil
  716.   "*Regexp for extension of files encrypted with `crypt-encryption-type.'
  717. Should be of the form \"\\\\(\\\\.foo\\\\)$\".  nil says use default values in
  718. `crypt-encryption-alist.'  If you change this after crypt++ is loaded then do
  719. \\[crypt-rebuild-tables]."
  720.   :type 'regexp
  721.   :group 'crypt)
  722.  
  723. (defcustom crypt-never-ever-decrypt nil
  724.   "*t says never attempt to decrypt a buffer."
  725.   :type 'boolean
  726.   :group 'crypt)
  727.  
  728. (defcustom crypt-auto-write-buffer-encrypted nil
  729.   "*t says files with `crypt-encryption-alist' file extension auto-encrypted.
  730. nil says query.  See `crypt-auto-write-buffer.'"
  731.   :type 'boolean
  732.   :group 'crypt)
  733.  
  734. (defcustom crypt-confirm-password nil
  735.   "*t says confirm new passwords and when writing a newly encrypted buffer."
  736.   :type 'boolean
  737.   :group 'crypt)
  738.  
  739. (defcustom crypt-encoded-disable-auto-save t
  740.   "*If t, turn off auto-save-mode for buffers which are encoded.
  741. If non-nil but not t, then no message is displayed.
  742.  
  743. The default is t is because there isn't any way to tell emacs to encode the
  744. autosave file, so the autosave would be in a different format from the
  745. original.  The disadvantage of turning off autosaves is that any work you
  746. do in that buffer will be completely lost if the changes are not explicitly
  747. saved.
  748.  
  749. It is probably best to set this variable to nil and use buffer-local
  750. variables in files for which you don't actually care about autosaves.
  751. Unencoded recovery data is better than none at all."
  752.   :type '(choice (const :tag "on" t)
  753.          (const :tag "off" nil)
  754.          (const :tag "no message" other))
  755.   :group 'crypt)
  756.  
  757. (defcustom crypt-encrypted-disable-auto-save t
  758.   "*If t, turn off auto-save-mode for buffers which are encrypted.
  759. If non-nil but not t, then no message is displayed.
  760.  
  761. The default is t is because there isn't any way to tell emacs to encrypt
  762. the autosave file, so the autosave would be in cleartext form.  The
  763. disadvantage of turning off autosaves is that any work you do in that
  764. buffer will be completely lost if the changes are not explicitly saved.
  765.  
  766. You might consider setting this variable to nil and use buffer-local
  767. variables in files for which security is more important than data
  768. recovery."
  769.   :type '(choice (const :tag "on" t)
  770.          (const :tag "off" nil)
  771.          (const :tag "no message" other))
  772.   :group 'crypt)
  773.  
  774. ;;; ENCRYPTION
  775.  
  776. ;;; Encrypted files have no magic number, so we have to hack a way of
  777. ;;; determining when a buffer should be decrypted.  we do this only buffers
  778. ;;; that match a MAGIC-REGEXP very close to beginning of buffer and that do
  779. ;;; _NOT_ match a MAGIC-REGEXP-INVERSE.
  780. ;;;  
  781. ;;; Currently MAGIC-REGEXP matches non-ASCII characters and
  782. ;;; MAGIC-REGEXP-INVERSE will match Sun OS, 4.x BSD, and Ultrix executable
  783. ;;; magic numbers, so binaries can still be edited (heh) without headaches.
  784.  
  785. (defconst crypt-encryption-magic-regexp "[\000\200-\237]"
  786.   "Regexp that must be found very close to beginning of encrypted buffer.
  787. This is intended to be an internal variable \(not user-visible\).  If you
  788. change this after crypt++ is loaded then do \\[crypt-rebuild-tables].")
  789.  
  790. (defconst crypt-encryption-magic-regexp-inverse
  791.   "\\`\201\001\\|^\\(..\\)?\\([\007\010\013]\001\\|\001[\007\010\013]\\)"
  792.   "Regexp that must *not* be found very close to beginning of encrypted buffer.
  793. This is intended to be an internal variable \(not user-visible\).  If you
  794. change this after crypt++ is loaded then do \\[crypt-rebuild-tables].")
  795.  
  796. (defconst crypt-magic-search-limit 100
  797.   "Limit of regular expression search used to recognize encrypted files.
  798. Maximum position in file for presence of `crypt-encryption-magic-regexp' and
  799. absence of `crypt-encryption-magic-regexp-inverse'.")
  800.  
  801. (defun crypt-build-encryption-alist ()
  802.   ;; Returns the encryption alist
  803.   (list
  804.    ;; crypt
  805.    (list 'crypt
  806.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  807.          (or crypt-encryption-file-extension "\\(\\.e\\)$")
  808.          "crypt" "crypt"
  809.          nil
  810.          nil
  811.          "Crypt"
  812.          nil
  813.          t
  814.          )
  815.    ;; DES (Cipher Block Chaining - CBC) [DES' default]
  816.    (list 'des
  817.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  818.          (or crypt-encryption-file-extension "\\(\\.des\\)$")
  819.          "des" "des"
  820.          '("-e" "-k")
  821.          '("-d" "-k")
  822.          "DES-CBC"
  823.          nil
  824.          t
  825.          )
  826.    ;; DES (Electronic Code Book - ECB)
  827.    (list 'des-ecb
  828.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  829.          (or crypt-encryption-file-extension "\\(\\.des\\)$")
  830.          "des" "des"
  831.          '("-e" "-b" "-k")
  832.          '("-d" "-b" "-k")
  833.          "DES-ECB"
  834.          nil
  835.          t
  836.          )
  837.    ;; PGP
  838.    (list 'pgp
  839.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  840.          (or crypt-encryption-file-extension "\\(\\.pgp\\)$")
  841.          "pgp" "pgp"
  842.          '("+batchmode" "+verbose=0" "-c" "-f" "-z")
  843.          '("+batchmode" "+verbose=0" "-f" "-z")
  844.          "PGP"
  845.          nil
  846.          t
  847.          )
  848.    ;; Add new elements here ...
  849.    ))
  850.  
  851. (defconst crypt-encryption-alist (crypt-build-encryption-alist)
  852.   "List of elements describing the encryption methods available.
  853. each element looks like
  854.  
  855.         \(ENCRYPTION-TYPE
  856.           MAGIC-REGEXP MAGIC-REGEXP-INVERSE
  857.           FILE-EXTENSION
  858.           ENCRYPT-PROGRAM DECRYPT-PROGRAM
  859.           ENCRYPT-ARGS
  860.           DECRYPT-ARGS
  861.           MINOR-MODE
  862.           GARBAGE-REGEXP-OR-LISPEXP
  863.           FILE-EXTENSION-TRICKS
  864.          \)
  865.  
  866. ENCRYPTION-TYPE is a symbol denoting the encryption type.
  867.  
  868. MAGIC-REGEXP regexp that must match very close to the beginning of an
  869. encrypted buffer.  This may also be some elisp expression to be evaluated at
  870. \(point-min\) that will return t for an encrypted buffer.  If this is set to
  871. nil then crypt++ will never try to decrypt a buffer.  Currently set to the
  872. internal variable `crypt-encryption-magic-regexp' which will match non-ASCII
  873. characters.
  874.  
  875. MAGIC-REGEXP-INVERSE regexp that must _NOT_ match very close to the beginning
  876. of an encrypted buffer.  This may also be some elisp expression to be
  877. evaluated at \(point-min\) that will return t for a NON-encrypted buffer.
  878. If this is set to t then crypt++ will never try to decrypt a buffer.
  879. Currently set to the internal variable `crypt-encryption-magic-regexp-inverse'
  880. which will match Sun OS, 4.x BSD, and Ultrix executable magic numbers, so
  881. binaries can still be edited (heh) without headaches.
  882.  
  883. FILE-EXTENSION regexp denoting the file extension usually appended the
  884. filename of files encrypted with ENCRYPT-PROGRAM.  The variable
  885. `crypt-encryption-file-extension' will over ride the default.
  886.  
  887. ENCRYPT-PROGRAM name of executable file to be used for encryption.
  888.  
  889. DECRYPT-PROGRAM name of executable file to be used for decryption.
  890.  
  891. ENCRYPT-ARGS arguments to be passed to ENCRYPT-PROGRAM may be a string or a
  892. list of strings or nil.
  893.  
  894. DECRYPT-ARGS arguments to be passed to DECRYPT-PROGRAM may be a string or a
  895. list of strings or nil.
  896.  
  897. MINOR-MODE string denoting the name for the encrypted minor mode as it will
  898. appear in the mode line.
  899.  
  900. GARBAGE-REGEXP-OR-LISPEXP dummy variable for compatibility with encoding.
  901.  
  902. FILE-EXTENSION-TRICKS is t or nil depending on whether or not tricks
  903. converting between different encryption types can be done based on
  904. FILE-EXTENSION; typically t.
  905. ")
  906.  
  907.  
  908. ;;; ENCODING 
  909.  
  910. (defcustom crypt-auto-decode-buffer t
  911.   "*t says buffers visiting encoded files will be decoded automatically.
  912. nil means to ask before doing the decoding."
  913.   :type 'boolean
  914.   :group 'crypt)
  915.  
  916. (defcustom crypt-auto-write-buffer nil
  917.   "*t says save files with `crypt-encoding-alist' file extensions as encoded.
  918. nil says to ask before doing this encoding.  Similarly, buffers originating
  919. from encoded files to be written to files not ending in `crypt-encoding-alist'
  920. file extensions will be written in plain format automatically.  nil says to
  921. ask before doing this decoding."
  922.   :type 'boolean
  923.   :group 'crypt)
  924.  
  925. ;; This is an internal variable documented here and not in a DOCSTRING in
  926. ;; order to save memory.  If this variable's value has been changed from its
  927. ;; default, then it contains the answer to the question "Write out buffer
  928. ;; foobar using `compression-type'?".  This question is asked only if *plain*
  929. ;; buffer foobar is being written to disk *and* it has a provocative
  930. ;; `compression-type' file-name extension (see DOCSTRING for variable
  931. ;; crypt-auto-write-buffer).  The variable is local to all buffers with a
  932. ;; default value of 'ask so if the situation described above arises, then the
  933. ;; question is asked at least once, unless the user-defined variable
  934. ;; crypt-auto-write-buffer is non-nil.
  935. (defvar crypt-auto-write-answer-local 'ask)
  936. (make-variable-buffer-local 'crypt-auto-write-answer-local)
  937. (setq-default crypt-auto-write-answer-local 'ask)
  938. (put 'crypt-auto-write-answer-local 'permanent-local t) ; for v19 Emacs
  939. (put 'crypt-auto-write-answer-local 'preserved t)       ; for kill-fix.el
  940.  
  941. (defcustom crypt-query-if-interactive t
  942.   "*t says ask when saving buffers where `crypt-encoded-mode' was toggled.
  943. nil says that even if filename extension is plain (i.e., not listed in
  944. `crypt-encoding-alist') buffer will be written in an encoded format without
  945. asking.
  946.  
  947. This variable is designed for users that edit a plain file (with plain
  948. extension) and then toggle `(crypt-encoded-mode)' and do not wish to be
  949. queried every time that they save the buffer.
  950.  
  951. NOTE: if `(crypt-encoded-mode)' was not called interactively (the usual
  952. scenario) then the value of this variable has no effect on how the buffer is
  953. written to disk.  In such a case `crypt-no-extension-implies-plain' is then
  954. the relevant variable."
  955.   :type 'boolean
  956.   :group 'crypt)
  957.  
  958. (defcustom crypt-no-extension-implies-plain t
  959.   "*t says file extensions not in `crypt-encoding-alist' may be written plain.
  960. if `crypt-auto-write-buffer' is also t then any file ending in a plain
  961. extension is written in plain format automatically, otherwise query user.
  962.  
  963. nil says user works with encoded (compressed) files without file extensions
  964. and will not be queried each time they save these files.
  965.  
  966. NOTE: (1) this does not effect find-file (C-x C-f) since that works with a
  967. magic regexp.  (2) there is no way to distinguish between write-file and
  968. save-buffer so nil will mean that neither will query."
  969.   :type 'boolean
  970.   :group 'crypt)
  971.  
  972. (defcustom crypt-freeze-vs-fortran t
  973.   "*t says `.F' file extension denotes a frozen file not a Fortran file.
  974. If you change this variable after crypt++ has been loaded then do
  975. \\[crypt-rebuild-tables]."
  976.   :type 'boolean
  977.   :group 'crypt)
  978.  
  979. (defcustom crypt-compact-vs-C++ nil
  980.   "*t says `.C' file extension denotes a compacted file not a C++ file.
  981. If you change this variable after crypt++ has been loaded then do
  982. \\[crypt-rebuild-tables]."
  983.   :type 'boolean
  984.   :group 'crypt)
  985.  
  986. (defcustom crypt-ignored-filenames nil
  987.   "*List of regexp filenames for which encoded to plain conversion is not done.
  988. A filename with a plain extension, in encoded format, that is matched by one of
  989. these elements will be saved in encoded format without a query for conversion to
  990. plain format.
  991.  
  992. This variable is provided for users that want to compress their incoming mail
  993. for RMAIL and VM which look for files `RMAIL' and `INBOX,' respectively, to
  994. store incoming mail.  For example, the gzip extensions on `RMAIL.gz' and
  995. `INBOX.gz' can be removed, this variable set to '\(\"INBOX$\" \"RMAIL$\"\) and
  996. no query about conversion to plain format will be made."
  997.   :type '(repeat regexp)
  998.   :group 'crypt)
  999.  
  1000. (defcustom crypt-default-encoding "gzip"
  1001.   "*Default encoding type as string used when `crypt-encoded-mode' is toggled.
  1002. Must match one of the elements of `crypt-encoding-alist'."
  1003.   :type 'string
  1004.   :group 'crypt)
  1005.  
  1006. (defcustom crypt-dos-has-ctrl-z nil
  1007.   "t if this buffer had a ctrl-z stripped from end, otherwise, nil.
  1008. Buffer local and set by `crypt-dos-to-unix-region'"
  1009.   :type 'boolean
  1010.   :group 'crypt)
  1011. (make-variable-buffer-local 'crypt-dos-has-ctrl-z)
  1012. (setq-default crypt-dos-has-ctrl-z nil)
  1013. (put 'crypt-dos-has-ctrl-z 'permanent-local t) ; for v19 Emacs
  1014. (put 'crypt-dos-has-ctrl-z 'preserved t)       ; for kill-fix.el
  1015.  
  1016. (defun crypt-build-encoding-alist ()
  1017.   ;; Returns the encoding alist
  1018.   (list
  1019.    ;; compress 
  1020.    (list 'compress
  1021.          "\037\235" nil
  1022.          "\\(\\.Z\\)$"
  1023.          "compress" "uncompress"
  1024.          nil nil
  1025.          "Compress"
  1026.          nil
  1027.          t)
  1028.    ;; gzip (GNU zip)
  1029.    (list 'gzip
  1030.          "\037\213" nil
  1031.          "\\(\\.g?z\\)$"
  1032.          "gzip" "gzip"
  1033.          "--quiet" "--decompress --quiet"
  1034.          "Zip"
  1035.          nil
  1036.          t)
  1037.    ;; freeze
  1038.    (list 'freeze
  1039.          "\037\236\\|\037\237" nil
  1040.          "\\(\\.F\\)$"
  1041.          "freeze" "freeze"
  1042.          "" "-d"
  1043.          "Freeze"
  1044.          nil
  1045.          crypt-freeze-vs-fortran)
  1046.    ;; compact
  1047.    (list 'compact
  1048.          "\377\037" nil
  1049.          "\\(\\.C\\)$"
  1050.          "compact" "uncompact"
  1051.          nil nil
  1052.          "Compact"
  1053.          "^Compression *:.*\n"
  1054.          crypt-compact-vs-C++)
  1055.    ;; DOS
  1056.    (list 'dos
  1057.          "[^\n\r]*\r$" nil
  1058.          "\\(\\.DOS\\)$"
  1059.          'crypt-unix-to-dos-region 'crypt-dos-to-unix-region
  1060.          nil nil
  1061.          "Dos"
  1062.          nil
  1063.          nil)
  1064.    ;; Add new elements here ...
  1065.    ))
  1066.  
  1067. (defconst crypt-encoding-alist (crypt-build-encoding-alist)
  1068.   "List of elements describing the encoding methods available.
  1069. each element looks like
  1070.  
  1071.         \(ENCODING-TYPE
  1072.           MAGIC-REGEXP MAGIC-REGEXP-INVERSE
  1073.           FILE-EXTENSION
  1074.           ENCODE-PROGRAM DECODE-PROGRAM
  1075.           ENCODE-ARGS DECODE-ARGS
  1076.           MINOR-MODE
  1077.           GARBAGE-REGEXP-OR-LISPEXP
  1078.           FILE-EXTENSION-TRICKS
  1079.          \)
  1080.  
  1081. ENCODING-TYPE is a symbol denoting the encoding type.  Currently known
  1082. encodings are (compress compact freeze gzip).
  1083.  
  1084. MAGIC-REGEXP is a regexp that matches the magic number at the
  1085. beginning of files encoded with ENCODING-TYPE.
  1086.  
  1087. MAGIC-REGEXP-INVERSE dummy variable for compatibility with encryption.
  1088.  
  1089. FILE-EXTENSION is a string denoting the file extension usually
  1090. appended the filename of files encoded with ENCODING-TYPE.
  1091.  
  1092. ENCODE-PROGRAM is a string denoting the name of the executable used to
  1093. encode files.
  1094.  
  1095. DECODE-PROGRAM is a string denoting the name of the executable used to
  1096. decode files.
  1097.  
  1098. ENCODE-ARGS arguments to be passed to ENCODE-PROGRAM may be a string or a
  1099. list of strings or nil.
  1100.  
  1101. DECODE-ARGS arguments to be passed to DECODE-PROGRAM may be a string or a
  1102. list of strings or nil.
  1103.  
  1104. MINOR-MODE is a string denoting the name for the encoded minor mode as 
  1105. it will appear in the mode line.
  1106.  
  1107. GARBAGE-REGEXP-OR-LISPEXP is (1) a regexp that matches any extraneous text
  1108. that is produced by the ENCODE-COMMAND including any newlines and will be
  1109. removed from the buffer before saving to disk; (2) a lisp expression that will
  1110. clean up extraneous material in the buffer or nil.  This is normally not
  1111. needed but can be derived for any ENCODE-COMMAND by checking the standard
  1112. error that results from `sh -c \"cat foo | ENCODE-COMMAND > bar\"'.
  1113.  
  1114. FILE-EXTENSION-TRICKS is t or nil depending on whether or not tricks
  1115. converting between different encoding types can be done based on
  1116. FILE-EXTENSION; typically t.
  1117. ")
  1118.  
  1119. (defvar crypt-inhibit-formats (when (featurep 'mule) '(dos))
  1120.   "*A list of crypt abilities to turn off.  In particular, setting this 
  1121. variable to be '(dos) will stop the dos-mode CRLF <-> LF damage.")
  1122.  
  1123.  
  1124. ;;; This allows the user to alter contents of the encoding and encryption
  1125. ;;; table variables without having to reload all of crypt++.
  1126. (defun crypt-rebuild-tables ()
  1127.   "Rebuilds the encryption and encoding tables and `minor-mode-alist'.
  1128. Allows user to alter variables used in building these tables.  May be called
  1129. interactively or in an initialization file.  Part of `after-init-hook'."
  1130.   (interactive)
  1131.   (setq crypt-encryption-alist (crypt-build-encryption-alist)
  1132.         crypt-encoding-alist (crypt-build-encoding-alist))
  1133.   (crypt-rebuild-minor-modes-alist))
  1134.  
  1135.  
  1136. ;;; Buffer locals.
  1137.  
  1138. (defvar crypt-buffer-save-encrypted nil
  1139.   "*non-nil says save buffer encrypted with `crypt-encryption-type.'
  1140. local to all buffers.")
  1141. (make-variable-buffer-local 'crypt-buffer-save-encrypted)
  1142. (put 'crypt-buffer-save-encrypted 'permanent-local t) ; for v19 Emacs
  1143. (put 'crypt-buffer-save-encrypted 'preserved t)       ; for kill-fix.el
  1144.  
  1145. (defvar crypt-buffer-encryption-key nil
  1146.   "*Key used for encryption of current buffer.  Local to all buffers.")
  1147. (make-variable-buffer-local 'crypt-buffer-encryption-key)
  1148. (put 'crypt-buffer-encryption-key 'permanent-local t) ; for v19 Emacs
  1149. (put 'crypt-buffer-encryption-key 'preserved t)       ; for kill-fix.el
  1150.  
  1151. (defvar crypt-buffer-save-encoded nil
  1152.   "*non-nil says buffer will be saved encoded.  Local to all buffers.")
  1153. (make-variable-buffer-local 'crypt-buffer-save-encoded)
  1154. (put 'crypt-buffer-save-encoded 'permanent-local t)   ; for v19 Emacs
  1155. (put 'crypt-buffer-save-encoded 'preserved t)         ; for kill-fix.el
  1156.  
  1157. (defvar crypt-buffer-encoding-type nil
  1158.   "*non-nil says buffer is encoded with ENCODING-TYPE.  Local to all buffers.")
  1159. (make-variable-buffer-local 'crypt-buffer-encoding-type)
  1160. (put 'crypt-buffer-encoding-type 'permanent-local t)  ; for v19 Emacs
  1161. (put 'crypt-buffer-encoding-type 'preserved t)        ; for kill-fix.el
  1162.  
  1163. (defvar crypt-buffer-interactive-encoded-mode nil
  1164.   "t says `crypt-encoded-mode' was toggled interactively, almost always nil.
  1165. Local to all buffers.")
  1166. (make-variable-buffer-local 'crypt-buffer-interactive-encoded-mode)
  1167. (put 'crypt-buffer-interactive-encoded-mode 'permanent-local t) ; v19 Emacs
  1168. (put 'crypt-buffer-interactive-encoded-mode 'preserved t)       ; kill-fix.el
  1169.  
  1170.  
  1171. ;;; Functions and macros that search `crypt-encryption-alist' and
  1172. ;;; `crypt-encoding-alist'.
  1173.  
  1174. (defun crypt-get-alist-member (type n)
  1175.   ;; Returns TYPE's Nth element
  1176.   (nth n (or (assoc type crypt-encryption-alist)
  1177.              (assoc type crypt-encoding-alist))))
  1178.  
  1179. (defmacro crypt-get-magic-regexp (type)
  1180.   ;; Returns regexp found at top of files encoded/encrypted with TYPE.
  1181.   (list 'crypt-get-alist-member type 1))
  1182.  
  1183. (defmacro crypt-get-magic-regexp-inverse (type)
  1184.   ;; Returns regexp *not* found at top of files encoded/encrypted with TYPE.
  1185.   (list 'crypt-get-alist-member type 2))
  1186.  
  1187. (defmacro crypt-get-file-extension (type)
  1188.   ;; Returns regexp matching extension of files encoded/encrypted with TYPE.
  1189.   (list 'crypt-get-alist-member type 3))
  1190.  
  1191. (defmacro crypt-get-encoding-program (type)
  1192.   ;; Returns name of program, as string, used to encode/encrypt with TYPE.
  1193.   (list 'crypt-get-alist-member type 4))
  1194.  
  1195. (defmacro crypt-get-decoding-program (type)
  1196.   ;; Returns name of program, as string, used to decode/decrypt with TYPE.
  1197.   (list 'crypt-get-alist-member type 5))
  1198.  
  1199. (defmacro crypt-get-encoding-args (type)
  1200.   ;; Returns arguments passed to program used to encode/encrypt with TYPE.
  1201.   (list 'crypt-get-alist-member type 6))
  1202.  
  1203. (defmacro crypt-get-decoding-args (type)
  1204.   ;; Returns arguments passed to program used to decode/decrypt with TYPE.
  1205.   (list 'crypt-get-alist-member type 7))
  1206.  
  1207. (defmacro crypt-get-minor-mode-name (type)
  1208.   ;; Returns minor mode name, as string, for encoding/encrypting with TYPE.
  1209.   (list 'crypt-get-alist-member type 8))
  1210.  
  1211. (defmacro crypt-get-cleanup-regexp (type)
  1212.   ;; Returns regexp or lisp-exp for cleaning up encoding/encrypting with TYPE.
  1213.   (list 'crypt-get-alist-member type 9))
  1214.  
  1215. (defmacro crypt-get-extension-tricks (type)
  1216.   ;; Returns t if file extension tricks doable for encoding/encrypting with
  1217.   ;; TYPE.
  1218.   (list 'crypt-get-alist-member type 10))
  1219.  
  1220. (defun crypt-buffer-save-name (type)
  1221.   ;; Returns variable `crypt-buffer-save-TYPE', set to t if encoding with TYPE.
  1222.   ;; local to all buffers.
  1223.   (intern (concat "crypt-buffer-save-" (symbol-name type))))
  1224.  
  1225.  
  1226. ;;; Create a buffer-local variable for each type of encoding.
  1227. ;;; These variables are used to trigger the minor mode names.
  1228.  
  1229. (defun crypt-build-minor-mode-alist ()
  1230.   ;; Returns minor mode alist entries for encoded and encrypted buffers.
  1231.   (append
  1232.    ;; First the encrypted minor mode -- only one.
  1233.    (list (list 'crypt-buffer-save-encrypted
  1234.                (concat " " (crypt-get-minor-mode-name crypt-encryption-type))))
  1235.    ;; Now the encoding minor modes.
  1236.    (mapcar
  1237.     (function
  1238.      (lambda (element)
  1239.        (let ((variable (crypt-buffer-save-name (car element))))
  1240.          (make-variable-buffer-local variable)
  1241.          (put variable 'permanent-local t) ; for v19 Emacs
  1242.          (put variable 'preserved t)       ; for kill-fix.el
  1243.          (list variable
  1244.                (concat " " (crypt-get-minor-mode-name (car element)))))))
  1245.     crypt-encoding-alist)))
  1246.  
  1247. (defconst crypt-minor-mode-alist (crypt-build-minor-mode-alist)
  1248.   "Alist containing encoded and encrypted minor modes.
  1249. Derived from variable `crypt-encoding-alist' and function
  1250. `crypt-build-minor-mode-encrypted'")
  1251.  
  1252. (defun crypt-rebuild-minor-modes-alist ()
  1253.   ;; Rebuilds the encryption and encoding minor modes and `minor-mode-alist.'
  1254.   ;; Allows user to alter variables used in building this alist. Called by
  1255.   ;; `crypt-rebuild-tables' and so part of `after-init-hook'."
  1256.  
  1257.   ;; First remove old crypt minor mode entries from `minor-mode-alist'.
  1258.   (if (memq (car crypt-minor-mode-alist) minor-mode-alist)
  1259.       (let ((alist crypt-minor-mode-alist) elt)
  1260.         (while (and alist (setq elt (car alist)))
  1261.           (setq minor-mode-alist (delq elt minor-mode-alist)
  1262.                 alist (cdr alist)))))
  1263.  
  1264.   ;; Get new crypt minor mode entries and add to minor-mode-alist.
  1265.   (setq crypt-minor-mode-alist (crypt-build-minor-mode-alist)
  1266.         minor-mode-alist (append crypt-minor-mode-alist minor-mode-alist)))
  1267.  
  1268.  
  1269. (defmacro crypt-save-point (&rest body)
  1270.   ;; Save value of point, evaluate FORMS, and restore value of point.  If the
  1271.   ;; saved value of point is no longer valid go to (point-max).  This macro
  1272.   ;; exists because, save-excursion loses track of point during some types of
  1273.   ;; deletions.
  1274.   (let ((var (make-symbol "saved-point")))
  1275.     (list 'let (list (list var '(point)))
  1276.           (list 'unwind-protect
  1277.                 (cons 'progn body)
  1278.                 (list 'goto-char var)))))
  1279.  
  1280.  
  1281. (defun crypt-find-file-hook ()
  1282.  
  1283.   ;; Hook run for decoding and/or decrypting the contents of a buffer.  Meant
  1284.   ;; to be called as part of `find-file-hooks'
  1285.  
  1286.   (let ((buffer-file-name buffer-file-name)
  1287.         (old-buffer-file-name buffer-file-name)
  1288.         (old-buffer-modified-p (buffer-modified-p))
  1289.         (case-fold-search nil) ; case-sensitive
  1290.         encrypted encoded buffer-read-only)
  1291.  
  1292.     ;; DECODE AND/OR DECRYPT
  1293.     (crypt-save-point
  1294.  
  1295.      ;; Do we have to DECODE? If not, then move on.
  1296.      (if (and (crypt-encoded-p)
  1297.               (or crypt-auto-decode-buffer
  1298.                   (y-or-n-p (format "Decode %s? " (buffer-name)))))
  1299.  
  1300.          ;; Decode, uncompress, the buffer.
  1301.          (progn
  1302.          
  1303.          (if (and (not (null buffer-file-name))
  1304.                   (string-match "\\.Z$" buffer-file-name))
  1305.              (set-visited-file-name
  1306.               (substring buffer-file-name 0 (match-beginning 0)))
  1307.            (if (and (not (null buffer-file-name))
  1308.                     (string-match "\\.gz$" buffer-file-name))
  1309.                (set-visited-file-name
  1310.                 (substring buffer-file-name 0 (match-beginning 0)))))
  1311.            (message "Decoding %s..." (buffer-name))
  1312.            (crypt-encode-buffer t)
  1313.  
  1314.            ;; Store the encoding mode.
  1315.  
  1316.            ;; We can not yet go into the minor modes because the major mode
  1317.            ;; may change later on and blow away all local variables (and thus
  1318.            ;; the minor modes).  Only needed for vanilla v18.  Our
  1319.            ;; buffer-locals defined 'permanent-local for v19 Emacs and
  1320.            ;; 'preserved for kill-fix.el.
  1321.  
  1322.            (setq encoded crypt-buffer-encoding-type)
  1323.  
  1324.            ;; Strip encoded file's extension so later we can set buffer's
  1325.            ;; major mode based on its file-name sans encoding extension.
  1326.            (if (string-match (crypt-get-file-extension
  1327.                               crypt-buffer-encoding-type) buffer-file-name)
  1328.                (setq buffer-file-name
  1329.                      (substring buffer-file-name 0 (match-beginning 1))))
  1330.  
  1331.            ;; Decoding ends.
  1332.            (if (not (input-pending-p))
  1333.                (message "Decoding %s... done" (buffer-name)))))
  1334.  
  1335.      ;; Do we have to DECRYPT? If not, then move on.
  1336.      (if (crypt-encrypted-p)
  1337.  
  1338.          ;; Decrypt buffer.
  1339.          (progn
  1340.                  
  1341.            (message "Decrypting %s..." (buffer-name))
  1342.            (crypt-encrypt-buffer crypt-buffer-encryption-key t)
  1343.                  
  1344.            ;; Save key in case major mode blows all buffer-locals. 
  1345.  
  1346.            ;; Only needed for vanilla v18.  Our buffer-locals defined
  1347.            ;; 'permanent-local for v19 Emacs and 'preserved for
  1348.            ;; kill-fix.el.
  1349.                
  1350.            (setq encrypted crypt-buffer-encryption-key)
  1351.                  
  1352.            ;; Strip encrypted file's extension so later we can set buffer's
  1353.            ;; major mode based on its file-name sans encrypting extension.
  1354.            (if (and (crypt-get-extension-tricks crypt-encryption-type)
  1355.                     (string-match (crypt-get-file-extension
  1356.                                    crypt-encryption-type) buffer-file-name))
  1357.                (setq buffer-file-name
  1358.                      (substring buffer-file-name 0 (match-beginning 1))))
  1359.  
  1360.            (if (not (input-pending-p))
  1361.                (message "Decrypting %s... done" (buffer-name))))))
  1362.  
  1363.     ;; MAJOR AND MINOR MODES
  1364.  
  1365.     ;; OK, if any changes have been made to the buffer we need to rerun the
  1366.     ;; code the does automatic selection of major mode.
  1367.  
  1368.     (if (or encoded encrypted)
  1369.  
  1370.         (progn
  1371.  
  1372.           ;; Set the major mode.
  1373.           (set-auto-mode)
  1374.           (hack-local-variables)
  1375.           
  1376.           ;; Now set our own minor mode(s).
  1377.           (if encoded
  1378.               ;; Recover encoding type, may have been smashed by major mode,
  1379.               ;; and toggle encoded mode.
  1380.               (progn (setq crypt-buffer-encoding-type encoded)
  1381.                      (crypt-encoded-mode 1)))
  1382.           
  1383.           (if encrypted
  1384.               ;; Recover encryption key, may have been smashed by major mode,
  1385.               ;; and toggle encrypted mode.
  1386.               (progn (setq crypt-buffer-encryption-key encrypted)
  1387.                      (crypt-encrypted-mode 1)))
  1388.           
  1389.           ;; Restore buffer file name now, so that lock file entry is removed
  1390.           ;; properly.
  1391.           (setq buffer-file-name old-buffer-file-name)
  1392.           
  1393.           ;; Restore buffer modified flag to its previous value.  Will also
  1394.           ;; remove lock file entry for buffer if previous value was nil.
  1395.           ;; This is why buffer-file-name had to be restored manually above.
  1396.           (set-buffer-modified-p old-buffer-modified-p)))))
  1397.  
  1398. (defun crypt-encoded-p (&optional buffer)
  1399.   ;; Returns t if current buffer, or optionally BUFFER, is encoded.
  1400.   ;; Sets `crypt-buffer-encoding-type' to encoding method.
  1401.   (save-excursion
  1402.     (and buffer (set-buffer buffer))
  1403.     (save-restriction
  1404.       (widen)
  1405.       (goto-char (point-min))
  1406.       (let ((alist crypt-encoding-alist) elt found)
  1407.         (while (and alist (setq elt (car alist)) (not found))
  1408.           (if (and (looking-at (nth 1 elt))
  1409.            (not (memq (nth 0 elt) crypt-inhibit-formats)))
  1410.               (setq crypt-buffer-encoding-type (nth 0 elt)
  1411.                     found t)
  1412.             ;; Decrement
  1413.             (setq alist (cdr alist))))
  1414.         found))))
  1415.  
  1416. (defun crypt-encrypted-p (&optional buffer)
  1417.   ;; Returns t if current buffer, or optionally BUFFER, is encrypted.
  1418.   ;; Look for MAGIC-REGEXP and absence of MAGIC-REGEXP-INVERSE.  If so, then
  1419.   ;; assume it is an encrypted buffer.
  1420.   ;; Sets `crypt-buffer-encryption-key' to password if not set already.
  1421.  
  1422.   ;; Do not try to decrypt buffer if not wanted.
  1423.   (if (not crypt-never-ever-decrypt)
  1424.  
  1425.       (save-excursion
  1426.         (and buffer (set-buffer buffer))
  1427.  
  1428.         (save-restriction
  1429.           (widen)
  1430.           (goto-char (point-min))
  1431.  
  1432.           (let ((magic-regexp (crypt-get-magic-regexp crypt-encryption-type))
  1433.                 (magic-regexp-inverse (crypt-get-magic-regexp-inverse
  1434.                                        crypt-encryption-type))
  1435.                 (limit (min (point-max) crypt-magic-search-limit)))
  1436.  
  1437.             ;; Check all encryption conditions.  If any fail, then return nil
  1438.             ;; value of this if-form, else check for password.
  1439.             (if (and
  1440.  
  1441.                  ;; Check for existence of MAGIC-REGEXP.
  1442.                  (if (stringp magic-regexp)
  1443.                      ;; regular expression
  1444.                      (re-search-forward magic-regexp limit t)
  1445.                    ;; lisp expression
  1446.                    (eval magic-regexp))
  1447.  
  1448.                  (goto-char (point-min))
  1449.  
  1450.                  ;; Check for absence of MAGIC-REGEXP-INVERSE.
  1451.                  (not (if (stringp magic-regexp-inverse)
  1452.                           ;; regular expression
  1453.                           (re-search-forward magic-regexp-inverse limit t)
  1454.                         ;; lisp expression
  1455.                         (eval magic-regexp-inverse))))
  1456.  
  1457.                 (progn
  1458.  
  1459.                   ;; Get key, i.e., the password?
  1460.                   (or crypt-buffer-encryption-key
  1461.                       ;; Do not confirm on reading an encrypted file.
  1462.                       (let ((crypt-confirm-password nil))
  1463.                         (call-interactively 'crypt-set-encryption-key)))
  1464.              
  1465.                   ;; Do not turn on encryption mode if no key: may be a binary
  1466.                   ;; file.  Thanks to Paul Dworkin (paul@media-lab.media.mit.edu).
  1467.                   (if (equal crypt-buffer-encryption-key "")
  1468.                       ;; Return nil.
  1469.                       (progn
  1470.                         (message "No key given.  Assumed normal.")
  1471.                         nil)
  1472.                     ;; Return t.
  1473.                     t))))))))
  1474.  
  1475.  
  1476. ;;; 
  1477.  
  1478. (defun crypt-check-extension-for-encoding ()
  1479.  
  1480.   ;; Checks file extensions for possible toggling of encoding modes.  Used for
  1481.   ;; buffers to be written to disk and called by `crypt-write-file-hook'
  1482.  
  1483.   ;; We try to flag a buffer to be written out in encoded form if the file
  1484.   ;; ends in one of the file-extensions in `crypt-encoding-alist' even if
  1485.   ;; `crypt-buffer-save-encoded' is nil.  Conversely, we try to write out a
  1486.   ;; buffer as a plain file if it does _not_ end in one of these
  1487.   ;; file-extensions even if `crypt-buffer-save-encoded' is non-nil.
  1488.   
  1489.   (let ((alist crypt-encoding-alist)
  1490.         (case-fold-search nil)
  1491.         found elt)
  1492.  
  1493.     ;; Search through the file name extensions for a match.
  1494.     (while (and alist (setq elt (car alist)) (not found))
  1495.       (if (string-match (nth 3 elt) buffer-file-name)
  1496.           (setq found t)
  1497.         ;; Decrement.
  1498.         (setq alist (cdr alist))))
  1499.     
  1500.     ;; Did we find a match? 
  1501.     (if found
  1502.         
  1503.         ;; File name ends in a very provocative extension.
  1504.  
  1505.         ;; Check to see if already an encoded file.
  1506.         (if crypt-buffer-save-encoded
  1507.             
  1508.             ;; Already encoded - do the methods of encoding match?
  1509.             (if (not (eq (nth 0 elt) crypt-buffer-encoding-type))
  1510.                  
  1511.                 ;; A new encoding method is desired.
  1512.  
  1513.                 ;; Can we play some filename extension tricks with the 
  1514.                 ;; destination extension?
  1515.                 (if (crypt-get-extension-tricks (nth 0 elt))
  1516.  
  1517.                     ;; Can play tricks.
  1518.                     ;; Change the method of encoding?
  1519.                     (if (crypt-y-or-n-p (format "Write %s using %s? "
  1520.                                          (buffer-name) (nth 4 elt)))
  1521.                 
  1522.                         ;; Case one.
  1523.                         ;; Turn off original encoding and turn on new encoding.
  1524.                         (progn (crypt-encoded-mode -1)
  1525.                                (setq crypt-buffer-encoding-type (nth 0 elt))
  1526.                                (crypt-encoded-mode 1)))
  1527.  
  1528.                   ;; Can not play tricks - maybe wants a plain file?
  1529.                   (if (crypt-y-or-n-p (format "Write %s a plain file? "
  1530.                                               (buffer-name)))
  1531.  
  1532.                       ;; Case three.
  1533.                       ;; Turn off the minor mode and _then_ the flags.
  1534.                       (progn
  1535.                         (crypt-encoded-mode -1)
  1536.                         (setq crypt-buffer-save-encoded nil
  1537.                               crypt-buffer-encoding-type nil)))))
  1538.           
  1539.           ;; Was a plain file.
  1540.           (if (and
  1541.                ;; Can we play some filename extension tricks?
  1542.                ;; If not then we must abort.
  1543.                (crypt-get-extension-tricks (nth 0 elt))
  1544.  
  1545.                (crypt-y-or-n-p (format "Write %s using %s? "
  1546.                                        (buffer-name) (nth 4 elt))))
  1547.               
  1548.               ;; Case two.
  1549.               ;; Turn on encoding flags and _then_ the minor mode.
  1550.               (progn 
  1551.                 (setq crypt-buffer-save-encoded t
  1552.                       crypt-buffer-encoding-type (nth 0 elt))
  1553.                 (crypt-encoded-mode 1))))
  1554.       
  1555.       ;; No match - a plain-jane file extension - but if the encoded flag is
  1556.       ;; non-nil then the user may really want it written out in plain
  1557.       ;; format so we must override this flag.
  1558.       (if (and crypt-buffer-save-encoded
  1559.                
  1560.                ;; Search the list of files to be ignored.
  1561.                ;; If `crypt-ignored-filenames' is nil then this let form 
  1562.                ;; will return t.  If a match is found this form will return 
  1563.                ;; nil.  Otherwise it will return t.
  1564.                (let ((tlist crypt-ignored-filenames)
  1565.                      case-fold-search found elt)
  1566.  
  1567.                  ;; Search through the list of filenames for a match.
  1568.                  (while (and tlist (setq elt (car tlist)) (not found))
  1569.                    (if (string-match elt buffer-file-name)
  1570.                        (setq found t)
  1571.                      ;; Decrement.
  1572.                      (setq tlist (cdr tlist))))
  1573.                  
  1574.                  ;; Return t if we can _not_ find a match.
  1575.                  (not found))
  1576.  
  1577.                ;; If `(crypt-encoded-mode)' was called interactively, then
  1578.                ;; there is a high probability that no matter what the file
  1579.                ;; name extension the user wishes to write the file out in some
  1580.                ;; encoded format.  Thanks to Kimball Collins
  1581.                ;; <kpc@ptolemy.arc.nasa.gov> for pointing out the need for
  1582.                ;; this.  Unfortunately, still can not distinguish between
  1583.                ;; write-file and save-buffer.  In the former the user may want
  1584.                ;; to write in plain format (or indeed some other format).
  1585.                
  1586.                (if crypt-buffer-interactive-encoded-mode
  1587.                    ;; Interactive
  1588.                    crypt-query-if-interactive 
  1589.                  ;; Non-interactive but still may want encoded format.
  1590.                  crypt-no-extension-implies-plain)
  1591.  
  1592.                (crypt-y-or-n-p (format "Write %s as a plain file? "
  1593.                                        (buffer-name))))
  1594.  
  1595.           ;; Case three.
  1596.           ;; Turn off the minor mode and _then_ the flags.
  1597.           (progn
  1598.             (crypt-encoded-mode -1)
  1599.             (setq crypt-buffer-save-encoded nil
  1600.                   crypt-buffer-encoding-type nil))))))
  1601.  
  1602.  
  1603. (defun crypt-y-or-n-p (prompt)
  1604.   ;; Queries user based on `crypt-auto-write-buffer' and internal buffer-local
  1605.   ;; variable `crypt-auto-write-answer-local'.  Returns value of
  1606.   ;; `crypt-auto-write-answer-local', which is t or nil.
  1607.  
  1608.   ;; Check if we need to ask user.  Should be 'ask, nil, or t.
  1609.   (if (eq crypt-auto-write-answer-local 'ask) ; Default value.
  1610.       ;; We may need to ask.
  1611.       (or crypt-auto-write-buffer
  1612.           ;; Ask and store the answer.  
  1613.           ;; Note: we only store if we asked.
  1614.           (setq crypt-auto-write-answer-local (y-or-n-p prompt)))
  1615.     ;; Use previous answer.
  1616.     crypt-auto-write-answer-local)) ; Will be nil or t.
  1617.  
  1618.  
  1619. ;;; This function should be called ONLY as a write-file hook.
  1620. ;;; Odd things will happen if it is called elsewhere.
  1621.  
  1622. (defun crypt-write-file-hook ()
  1623.   
  1624.   ;; Hook for possibly writing out file, and backup file, in a non-plain
  1625.   ;; format.  Terminates calls in `write-file-hooks' and should be at end of
  1626.   ;; list.
  1627.  
  1628.   ;; Check file-extension for possible toggling of encoding modes.
  1629.   (crypt-check-extension-for-encoding)
  1630.  
  1631.   ;; Check extension for encryption.
  1632.   (if (and
  1633.  
  1634.        ;; Maybe file ends with provocative extension w.r.t. encryption?
  1635.        (stringp (crypt-get-file-extension crypt-encryption-type))
  1636.        (let ((case-fold-search nil)) ; Make case-sensitive.
  1637.          (string-match (crypt-get-file-extension crypt-encryption-type)
  1638.                        buffer-file-name))
  1639.        
  1640.        ;; Can we play tricks?
  1641.        (crypt-get-extension-tricks crypt-encryption-type)
  1642.  
  1643.        ;; Match of filename extension - is file in plain format?
  1644.        (not crypt-buffer-save-encrypted)
  1645.        
  1646.        ;; Query?
  1647.        (or crypt-auto-write-buffer-encrypted
  1648.            (y-or-n-p
  1649.             (format "Write %s as an encrypted file? " (buffer-name)))))
  1650.  
  1651.       (progn
  1652.         ;; Set password and toggle `crypt-encrypted-mode'
  1653.         (call-interactively 'crypt-set-encryption-key)
  1654.         (crypt-encrypted-mode 1)))
  1655.  
  1656.   ;; Now decide whether or not we need to continue with this defun. Does the
  1657.   ;; buffer need to be saved in a non-plain form?  If not then writing is not
  1658.   ;; done here but later in the write-file-hooks - probably at the end.
  1659.  
  1660.   (if (or crypt-buffer-save-encoded crypt-buffer-save-encrypted)
  1661.       
  1662.       (save-excursion
  1663.         (save-restriction
  1664.  
  1665.           (let 
  1666.               
  1667.               ;; BINDINGS
  1668.               ((copy-buffer (get-buffer-create " *crypt copy buffer*"))
  1669.                (selective-display selective-display)
  1670.                (buffer-read-only))
  1671.             
  1672.             ;; FORMS
  1673.             (copy-to-buffer copy-buffer 1 (1+ (buffer-size)))
  1674.             (narrow-to-region (point) (point))
  1675.             
  1676.             (unwind-protect
  1677.                 
  1678.                 ;; BODYFORM
  1679.                 (let (setmodes)
  1680.  
  1681.                   ;; As of v19, if one of functions of the `write-file-hooks'
  1682.                   ;; returns a non-nil value, then `basic-save-buffer' no
  1683.                   ;; longer creates a backup file.  We must do it ourselves. 
  1684.                   ;; this should be a no-op in v18.
  1685.                   (or buffer-backed-up
  1686.                       (setq setmodes (backup-buffer)))
  1687.  
  1688.                   (insert-buffer-substring copy-buffer)
  1689.                   (kill-buffer copy-buffer)
  1690.                   
  1691.                   ;; "Who would cross the Bridge of Death
  1692.                   ;;  Must answer me
  1693.                   ;;  These questions three
  1694.                   ;;  Ere the other side he see."
  1695.                   ;;
  1696.                   ;; Bridgekeeper from Monty Python and the Holy Grail
  1697.                   
  1698.                   ;; [1] selective-display non-nil means we must convert
  1699.                   ;; carriage returns to newlines now, and set the variable
  1700.                   ;; selective-display temporarily to nil.
  1701.                   (if selective-display
  1702.                       (progn
  1703.                         (goto-char (point-min))
  1704.                         (subst-char-in-region (point-min) (point-max) ?\r ?\n)
  1705.                         (setq selective-display nil)))
  1706.                   
  1707.                   ;; [2] encryption
  1708.                   (if crypt-buffer-save-encrypted
  1709.                       (progn
  1710.                         ;; check for password
  1711.                         (if (not crypt-buffer-encryption-key)
  1712.                             (call-interactively 'crypt-set-encryption-key))
  1713.                         (if (null crypt-buffer-encryption-key)
  1714.                             (error "No encryption key set for buffer %s"
  1715.                                    (buffer-name)))
  1716.                         (if (not (stringp crypt-buffer-encryption-key))
  1717.                             (error "Encryption key is not a string"))
  1718.                         (message "Encrypting %s..." (buffer-name))
  1719.                         (crypt-encrypt-buffer crypt-buffer-encryption-key)))
  1720.                   
  1721.                   ;; [3] encoding
  1722.                   (if crypt-buffer-save-encoded
  1723.                       (progn
  1724.                         (message "Encoding %s..." (buffer-name))
  1725.                         (crypt-encode-buffer)))
  1726.                   
  1727.                   ;; Now write buffer/region to disk.
  1728.                   (write-region (point-min) (point-max) buffer-file-name nil t)
  1729.                   (delete-region (point-min) (point-max))
  1730.                   (set-buffer-modified-p nil)
  1731.                   
  1732.                   ;; Now that the file is written, set its modes.
  1733.                   (if setmodes
  1734.                       (condition-case ()
  1735.                           (set-file-modes buffer-file-name setmodes)
  1736.                         (error nil)))
  1737.  
  1738.                   ;; Return t so that `basic-save-buffer' will know that the
  1739.                   ;; save has already been done.
  1740.                   
  1741.                   ;; NOTE: this TERMINATES write-file-hooks so any hooks
  1742.                   ;; following this one will not be executed.
  1743.                   
  1744.                   t )
  1745.  
  1746.               ;; UNWINDFORMS
  1747.               ;; unwind...sit back...take a load off...have a beer 
  1748.  
  1749.               ;; If the encoded and encrypted stuff has already been removed
  1750.               ;; then this is a no-op.  This form is executed if BODYFORM
  1751.               ;; completes normally but the value of BODYFORM is returned -
  1752.               ;; i.e., t is returned.
  1753.  
  1754.               (delete-region (point-min) (point-max))))))))
  1755.  
  1756.               
  1757. ;;;; ENCRYPTION
  1758.  
  1759. (defun crypt-encrypt-region (start end key &optional decrypt)
  1760.   "Encrypt region START to END using KEY and `crypt-encryption-type'.  When
  1761. called interactively START and END default to point and mark \(START being the
  1762. lesser of the two\), and KEY is prompted for.  With optional DECRYPT non-nil,
  1763. decryption is done."
  1764.  
  1765.   (interactive
  1766.    (let (decrypt)
  1767.      (barf-if-buffer-read-only)
  1768.      (list (region-beginning)
  1769.            (region-end)
  1770.            (crypt-read-string-no-echo
  1771.             (concat (if (setq decrypt (y-or-n-p "Decrypt region? ")) "De" "En")
  1772.                     "crypt buffer using key: ")
  1773.             ;; Do not confirm on decrypting region.
  1774.             (if (not decrypt) crypt-confirm-password))
  1775.            decrypt)))
  1776.  
  1777.   (crypt-save-point
  1778.  
  1779.    ;; We define the PROGRAM as the encryption program or decryption program
  1780.    ;; listed for `crypt-encryption-type' of `crypt-encryption-alist.'  These
  1781.    ;; should be just the name of the executable and should _not_ contain any
  1782.    ;; arguments.  `(call-process-region)' would be confused if we tried to
  1783.    ;; pass the arguments as part of the PROGRAM.  The arguments are passed
  1784.    ;; through the encryption args or decryption args listed for
  1785.    ;; `crypt-encryption-type' of `crypt-encryption-alist.'
  1786.  
  1787.    ;; Thanks to Joe Ilacqua <spike@world.std.com> and others for pointing out
  1788.    ;; an error that occurs with some encryption programs (e.g., the crypt from
  1789.    ;; Sun Microsystems, HPUX-8, and BSD) if `args' is `"".'  This will allow
  1790.    ;; nil values and lists of strings for argument.
  1791.  
  1792.    (let (prog args)
  1793.  
  1794.      ;; Get the proper program and arguments.
  1795.      (if decrypt
  1796.          (setq prog (crypt-get-decoding-program crypt-encryption-type)
  1797.                args (crypt-get-decoding-args crypt-encryption-type))
  1798.        (setq prog (crypt-get-encoding-program crypt-encryption-type)
  1799.              args (crypt-get-encoding-args crypt-encryption-type)))
  1800.      
  1801.      ;; Check arguments.
  1802.      (cond
  1803.  
  1804.       ;; nil or "" args - don't pass.
  1805.       ((or (not args) (equal "" args))
  1806.        (call-process-region start end prog t t nil key))
  1807.        
  1808.       ;; Check if the args are in the form of a list - must use apply.
  1809.       ((listp args)
  1810.        (apply 'call-process-region
  1811.               (append (list start end prog t t nil) args (list key))))
  1812.        
  1813.       ;; Default - just a non-null string.
  1814.       (t
  1815.        (call-process-region start end prog t t nil args key))))))
  1816.    
  1817.      
  1818. (defun crypt-encrypt-buffer (key &optional decrypt buffer)
  1819.  
  1820.   ;; Use KEY to encrypt current buffer and with optional DECRYPT decrypt.
  1821.   ;; With optional BUFFER, encrypt or decrypt that buffer.  Not meant to be
  1822.   ;; called interactively, toggle `crypt-encrypted-mode' to encrypt an entire
  1823.   ;; buffer.
  1824.  
  1825.   (or buffer (setq buffer (current-buffer)))
  1826.   (save-excursion (set-buffer buffer)
  1827.                   (crypt-encrypt-region (point-min) (point-max) key decrypt)))
  1828.  
  1829.  
  1830. ;;;; ENCODING
  1831.  
  1832. (defun crypt-encode-region (start end &optional decode)
  1833.  
  1834.   "Encode region START to END.  When called interactively START and END
  1835. default to point and mark \(START being the lesser of the two\).  With
  1836. optional DECODE non-nil, decoding is done.
  1837.  
  1838. If encoding is attempted, then checks for correct magic number at start of
  1839. newly-encoded region.  If not found, then searches and deletes a user-defined
  1840. regexp, or executes a user-defined lisp expression, as defined in
  1841. `crypt-encoding-alist,' and checks again for magic number."
  1842.  
  1843.   (interactive "*r\nP")
  1844.  
  1845.   ;; If called interactively then we may need to determine the encoding type.
  1846.   (if (and (interactive-p) (not crypt-buffer-encoding-type))
  1847.       (crypt-read-encoding-type))
  1848.  
  1849.   (crypt-save-point
  1850.  
  1851.    ;; We define the PROGRAM as `shell-file-name' and have it call the encoding
  1852.    ;; or decoding program with the arguments.
  1853.  
  1854.    (let (prog args)
  1855.  
  1856.      ;; Get the proper program and arguments.
  1857.      (if decode
  1858.          (setq prog (crypt-get-decoding-program crypt-buffer-encoding-type)
  1859.                args (crypt-get-decoding-args crypt-buffer-encoding-type))
  1860.        (setq prog (crypt-get-encoding-program crypt-buffer-encoding-type)
  1861.              args (crypt-get-encoding-args crypt-buffer-encoding-type)))
  1862.  
  1863.      (cond 
  1864.  
  1865.       ;; prog is a string?
  1866.       ((stringp prog)
  1867.  
  1868.        ;; Check arguments.
  1869.        (cond
  1870.         
  1871.         ;; Check if the args are in the form of a list, will catch 'nil.
  1872.         ((listp args)
  1873.          
  1874.          ;; Cat all the strings together.
  1875.          (while args
  1876.            (setq prog (concat prog " " (car args))
  1877.                  args (cdr args))))
  1878.         
  1879.         ;; Check if a non-null string.
  1880.         ((and (not (string= "" args))
  1881.               (not (eq args t))) ; just in case...
  1882.          (setq prog (concat prog " " args))))
  1883.        
  1884.        (call-process-region start end shell-file-name t t nil "-c" prog))
  1885.       
  1886.       ;; Otherwise try and eval it.
  1887.       (t
  1888.        (eval (if args
  1889.                  (list prog start end args)
  1890.                (list prog start end))))))
  1891.    
  1892.    ;; Encoding or decoding region?
  1893.    (if (not decode)
  1894.  
  1895.        ;; Check if encoded region starts with magic number.
  1896.        (let ((magic (crypt-get-magic-regexp crypt-buffer-encoding-type))
  1897.              (clean (crypt-get-cleanup-regexp crypt-buffer-encoding-type))
  1898.              (case-fold-search nil))
  1899.          
  1900.          ;; Top of region.
  1901.          (goto-char start)
  1902.          
  1903.          ;; Check for magic number.
  1904.          (if (not (looking-at magic))
  1905.              
  1906.              ;; Magic number not there. 
  1907.  
  1908.              ;; Some compression programs produce an (inane) standard error
  1909.              ;; message that gets piped into the buffer.  For example, some
  1910.              ;; versions of compact output "Compression : 35.50%."  There may
  1911.              ;; be some way to clean up buffer and check again.
  1912.  
  1913.              (cond
  1914.  
  1915.               ;; No mechanism to clean up - failed.
  1916.               ((eq clean nil)
  1917.                (error "Encoding failed!"))
  1918.  
  1919.               ;; Cleanup a regexp string?
  1920.               ((stringp clean)
  1921.  
  1922.                ;; Is regexp there?
  1923.                (if (looking-at clean)
  1924.  
  1925.                    (progn
  1926.                      ;; Delete the match.
  1927.                      (delete-region (match-beginning 0) (match-end 0))
  1928.  
  1929.                      ;; Check for magic again.
  1930.                      (if (not (looking-at magic))
  1931.                          (error "Encoding failed!")))))
  1932.                
  1933.               ;; Default: evaluate a lisp expression and check again.
  1934.               (t (eval clean)
  1935.                  (if (not (looking-at magic))
  1936.                      (error "Encoding failed!")))))))))
  1937.  
  1938. (defun crypt-encode-buffer (&optional decode buffer)
  1939.  
  1940.   ;; Encode current buffer.  With optional DECODE non-nil decode and optional
  1941.   ;; BUFFER, encode or decode that buffer.  Not meant to be called
  1942.   ;; interactively, toggle `crypt-encoded-mode' to encode an entire buffer.
  1943.  
  1944.   (or buffer (setq buffer (current-buffer)))
  1945.   (save-excursion (set-buffer buffer)
  1946.                   (crypt-encode-region (point-min) (point-max) decode)))
  1947.  
  1948.  
  1949. ;;;; DOS <--> UNIX
  1950. (defun crypt-dos-to-unix-region (start end)
  1951.   "Converts region from START to END, from dos to unix format.
  1952. Replaces \"\\r\\n\" with \"\\n\" and, if exists, removes ^Z at end of file.
  1953. Sets `crypt-dos-has-ctrl-z'."
  1954.   (save-excursion
  1955.     (save-restriction
  1956.       (let ((remove-ctrl-z (equal end (point-max))))
  1957.         (narrow-to-region start end)
  1958.         (goto-char (point-min))
  1959.         (while (search-forward "\r\n" nil t)
  1960.           (replace-match "\n" nil t))
  1961.         (if remove-ctrl-z
  1962.             (progn
  1963.               (goto-char (1- (point-max)))
  1964.               (setq crypt-dos-has-ctrl-z (looking-at "\C-z"))
  1965.               (if crypt-dos-has-ctrl-z (replace-match ""))))))))
  1966.  
  1967. (defun crypt-unix-to-dos-region (start end)
  1968.   "Converts region from START to END, from unix to dos format.
  1969. Replaces \"\\n\" with \"\\r\\n\" and adds a ^Z at end of file if
  1970. `crypt-dos-has-ctrl-z' is non-nil."
  1971.   (save-excursion
  1972.     (save-restriction
  1973.       (let ((add-ctrl-z (and crypt-dos-has-ctrl-z
  1974.                             (equal end (point-max)))))
  1975.         (narrow-to-region start end)
  1976.         (goto-char (point-min))
  1977.         (while (search-forward "\n" nil t)
  1978.           (replace-match "\r\n" nil t))
  1979.         (if add-ctrl-z
  1980.             (progn
  1981.               (goto-char (point-max))
  1982.               (insert "\C-z")))))))
  1983.  
  1984.  
  1985. ;;;; MODES
  1986.  
  1987. (defun crypt-encrypted-mode (&optional arg)
  1988.  
  1989.   "Toggle encrypted mode.  With ARG, turn on iff positive, otherwise turn off.
  1990. minor mode in which buffers are automatically encrypted before being written.
  1991. if toggled and a key has been set for the current buffer, then the current
  1992. buffer is marked modified, since it needs to be rewritten with or without
  1993. encryption.
  1994.  
  1995. Entering encrypted mode causes auto-saving to be turned off in the current
  1996. buffer, as there is no way in Emacs Lisp to force auto save files to be
  1997. encrypted."
  1998.  
  1999.   (interactive "P")
  2000.   (let ((oldval crypt-buffer-save-encrypted))
  2001.     (setq crypt-buffer-save-encrypted
  2002.           (if arg (> arg 0) (not crypt-buffer-save-encrypted)))
  2003.  
  2004.     (if crypt-buffer-save-encrypted
  2005.         ;; We are going to save as encrypted, we will turn off auto-saving.
  2006.         (progn
  2007. ;; NEVER do this.  Turning off auto-saving is one thing.  But if there's
  2008. ;; already an autosave for some other reason, what business does this
  2009. ;; package have tampering with it?
  2010. ;          ;; If an auto-save file already exists, then delete it.
  2011. ;          (if (and (stringp buffer-auto-save-file-name)
  2012. ;                   (file-exists-p buffer-auto-save-file-name))
  2013. ;              (delete-file buffer-auto-save-file-name))
  2014.           ;; If the key is not set then ask for it.
  2015.           (if (not crypt-buffer-encryption-key)
  2016.               (call-interactively 'crypt-set-encryption-key))
  2017.           ;; Turn-off auto-saving if crypt-encrypted-disable-auto-save non-nil.
  2018.           (and crypt-encrypted-disable-auto-save
  2019.                auto-save-default
  2020.                (progn
  2021.                  (auto-save-mode 0)
  2022.                  (if (eq crypt-encrypted-disable-auto-save t)
  2023.                      (message "Auto-save off (in this buffer)")))))
  2024.  
  2025.       ;; We are not going to save as encrypted, we will turn on auto-saving
  2026.       ;; but only if we are editing a file and the default says we should.
  2027.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  2028.  
  2029.     (if crypt-buffer-encryption-key
  2030.         ;; Set buffer-modified flag to t only if the mode has been changed, 
  2031.         ;; old code set unconditionally to nil if mode was not changed .
  2032.         ;; Modification suggested by: Gerd Hillebrand <ggh@cs.brown.edu>
  2033.         (if (not (eq oldval crypt-buffer-save-encrypted))
  2034.             (set-buffer-modified-p t)))))
  2035.  
  2036.  
  2037. ;;; Forgetting encryption keys (by jwz)
  2038. ;;; This is really kind of bogus.  Good behavior would be:
  2039. ;;; - If a crypted buffer has not been "accessed" (edited? selected?
  2040. ;;;   viewed?) in N minutes, kill the buffer (since the plaintext is valuable.)
  2041. ;;; - If a crypted buffer is modified, but "idle", just forget the password
  2042. ;;;   instead of killing the buffer (though the plaintext is valuable, it's
  2043. ;;;   also unsaved...)
  2044. ;;; - The "idleness" of a modified buffer should be reset with every mod, so
  2045. ;;;   that an unsaved buffer that you have been constantly typing at for an
  2046. ;;;   hour doesn't lose its password.
  2047. ;;; - But, if a password for a buffer has been discarded, and then an attempt
  2048. ;;;   is made to save that buffer, then we should confirm that the newly-
  2049. ;;;   typed password is the same as the password used in the file on disk. 
  2050. ;;;   with PGP, we could check that by attempting to decrypt the file on
  2051. ;;;   disk into a scratch buffer and seeing if it contains the PGP error
  2052. ;;;   message.
  2053. ;;; - BUG: if a password has been forgotten, and you save, and are prompted,
  2054. ;;;   the old file has already been renamed to a backup!!  so if you ^G, the
  2055. ;;;   real file name no longer exists on disk - only as a ~ file.
  2056.  
  2057. (defun crypt-forget-encryption-key ()
  2058.   (cond (crypt-buffer-encryption-key
  2059.      (let ((inhibit-quit t))
  2060.        (fillarray crypt-buffer-encryption-key 0)
  2061.        (setq crypt-buffer-encryption-key nil))
  2062.      t)
  2063.     (t nil)))
  2064.  
  2065. (add-hook 'kill-buffer-hook 'crypt-forget-encryption-key)
  2066.  
  2067. (defcustom crypt-forget-passwd-timeout (* 60 60)
  2068.   "*Do not retain passwords for encrypted buffers more than this many seconds.
  2069. If nil, keep them indefinitely."
  2070.   :type '(choice integer (const :tag "indefinite" nil))
  2071.   :group 'crypt)
  2072.  
  2073. (defun crypt-reset-passwd-timer ()
  2074.   (if (fboundp 'get-itimer)    ; XEmacs, or anything with itimer.el loaded.
  2075.       (let ((name "crypt-forget-passwds"))
  2076.     (if (get-itimer name)
  2077.         (delete-itimer name))
  2078.     (if crypt-forget-passwd-timeout
  2079.         (start-itimer name
  2080.               'crypt-reset-passwds-timeout
  2081.               crypt-forget-passwd-timeout)))))
  2082.  
  2083. (defun crypt-reset-passwds-timeout ()
  2084.   ;; run by the timer code to forget all passwords
  2085.   (let ((buffers (buffer-list))
  2086.     (inhibit-quit t)
  2087.     (keep-going nil))
  2088.     (while buffers
  2089.       (save-excursion
  2090.     (set-buffer (car buffers))
  2091.     (cond ((and crypt-buffer-encryption-key
  2092.             (buffer-modified-p))
  2093.            ;; don't forget the password in modified buffers, but
  2094.            ;; do check again later (maybe it will be unmodified.)
  2095.            (setq keep-going t))
  2096.           (crypt-buffer-encryption-key
  2097.            ;; forget the password in unmodified buffers.
  2098.            (crypt-forget-encryption-key)
  2099.            ;; Mark the buffer read only so that it's not accidentally
  2100.            ;; edited; the smart thing to do is revert it, type the
  2101.            ;; encryption key (to make sure they same key is used)
  2102.            ;; and then edit it.
  2103.            (setq buffer-read-only t)
  2104.            (message "Password discarded in buffer %s"
  2105.             (buffer-name (car buffers))))
  2106.           ))
  2107.       (setq buffers (cdr buffers)))
  2108.     (if keep-going
  2109.     (crypt-reset-passwd-timer))
  2110.     nil))
  2111.  
  2112.  
  2113. ;;; Originally `tek-symbol-alist-to-table' from tek-highlight.el.
  2114. (defun crypt-symbol-alist-to-table (list)
  2115.   ;; Converts an alist of symbols to a table suitable for `completing-read.'
  2116.   ;; Called by `crypt-read-encoding-type'
  2117.   (mapcar (function (lambda (x) (list (symbol-name (car x)))))
  2118.           list))
  2119.  
  2120. (defun crypt-read-encoding-type ()
  2121.  
  2122.   ;; Function called to query user for `crypt-buffer-encoding-type' uses
  2123.   ;; contents of `crypt-encoding-alist' and `crypt-default-encoding.'
  2124.  
  2125.   ;; Use poor man's gmhist (i.e., we could have used gmhist's
  2126.   ;; `completing-read-with-history-in' instead).
  2127.   (let (
  2128.         ;; Find the encoding type desired by user.
  2129.         (type
  2130.          (completing-read
  2131.           (concat "encoding type (? for list): [" crypt-default-encoding "] ")
  2132.           (crypt-symbol-alist-to-table crypt-encoding-alist))))
  2133.     
  2134.     ;; Test length of object returned by `completing-read'.
  2135.     (if (zerop (length type))
  2136.         
  2137.         ;; Nothing there, i.e., user hit return -- use default.
  2138.         (setq crypt-buffer-encoding-type (intern crypt-default-encoding))
  2139.       
  2140.       ;; Use the value from mini-buffer and update the default value.
  2141.       (setq crypt-buffer-encoding-type (intern type)
  2142.             crypt-default-encoding type))))
  2143.  
  2144. (defun crypt-encoded-mode (&optional arg)
  2145.  
  2146.   "Toggle encoded mode.  With ARG, turn on iff positive, otherwise turn off.
  2147. minor mode in which buffers are automatically encoded before being written.  if
  2148. toggled then current buffer is marked modified, since it needs to be written
  2149. with or without encoding.
  2150.  
  2151. Entering encoded mode causes auto-saving to be turned off in the current
  2152. buffer, as there is no way in Emacs Lisp to force auto save files to be
  2153. encoded."
  2154.  
  2155.   (interactive "P")
  2156.  
  2157.   ;; Set flag indicating whether or not `(crypt-encoded-mode)' was called 
  2158.   ;; interactively.
  2159.   (setq crypt-buffer-interactive-encoded-mode (interactive-p))
  2160.  
  2161.   ;; If called interactively then need to determine encoding type.
  2162.   (if (and crypt-buffer-interactive-encoded-mode
  2163.            (not crypt-buffer-encoding-type))
  2164.       (crypt-read-encoding-type))
  2165.  
  2166.   ;; Save old value of `crypt-buffer-save-encoded'.
  2167.   (let ((oldval crypt-buffer-save-encoded))
  2168.  
  2169.     ;; Set the variable `crypt-buffer-save-encoded' to t if the argument is 
  2170.     ;; positive, otherwise toggle its current value.
  2171.     (setq crypt-buffer-save-encoded
  2172.           (if arg (> arg 0) (not crypt-buffer-save-encoded)))
  2173.  
  2174.     ;; Set the variable generated by `(crypt-buffer-save-name)' to the value
  2175.     ;; stored in `crypt-buffer-save-encoded.'
  2176.     (set-variable (crypt-buffer-save-name crypt-buffer-encoding-type)
  2177.                   crypt-buffer-save-encoded)
  2178.  
  2179.     (if crypt-buffer-save-encoded
  2180.         ;; We are going to save as encoded, we might turn off auto-saving.
  2181.         (progn
  2182. ;; NEVER do this.  Turning off auto-saving is one thing.  But if there's
  2183. ;; already an autosave for some other reason, what business does this
  2184. ;; package have tampering with it?
  2185. ;          ;; If an auto-save file already exists, then delete it.
  2186. ;          (if (and (stringp buffer-auto-save-file-name)
  2187. ;                   (file-exists-p buffer-auto-save-file-name))
  2188. ;              (delete-file buffer-auto-save-file-name))
  2189.           ;; Turn-off auto-saving if crypt-encoded-disable-auto-save non-nil.
  2190.           (and crypt-encoded-disable-auto-save
  2191.                auto-save-default
  2192.                (progn
  2193.                  (auto-save-mode 0)
  2194.                  (if (eq crypt-encoded-disable-auto-save t)
  2195.                      (message "Auto-save off (in this buffer)")))))
  2196.  
  2197.       ;; We are not going to save as encoded, we will turn on auto-saving but
  2198.       ;; only if we are editing a file and the default says we should.
  2199.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  2200.  
  2201.     ;; Have we toggled the mode? 
  2202.  
  2203.     ;; If yes, then mark buffer as modified.  If not, then leave
  2204.     ;; buffer-modified flag alone.
  2205.  
  2206.     ;; The old code previously set the variable `set-buffer-modified-p' to a
  2207.     ;; value of t if there was a mode change and (unconditionally) to nil
  2208.     ;; if there was not a mode change.
  2209.  
  2210.     ;; Modification suggested by: Gerd Hillebrand <ggh@cs.brown.edu>.
  2211.  
  2212.     (if (not (eq oldval crypt-buffer-save-encoded))
  2213.         (set-buffer-modified-p t))))
  2214.  
  2215.  
  2216. ;;;; Additional encryption functions
  2217.  
  2218. ;; For Emacs V18 compatibility
  2219. (and (not (fboundp 'buffer-disable-undo))
  2220.      (fboundp 'buffer-flush-undo)
  2221.      (fset 'buffer-disable-undo 'buffer-flush-undo))
  2222.  
  2223. (fset 'crypt-read-string-no-echo 'read-passwd)
  2224.  
  2225. ;(defun crypt-read-string-no-echo (prompt &optional confirm)
  2226. ;
  2227. ;  ;; Read a string from minibuffer, prompting with PROMPT, echoing periods.
  2228. ;  ;; Optional second argument CONFIRM non-nil means that the user will be
  2229. ;  ;; asked to type the string a second time for confirmation and if there is a
  2230. ;  ;; mismatch, the whole process is repeated.
  2231. ;  ;;
  2232. ;  ;;         Line editing keys are --
  2233. ;  ;;           C-h, DEL      rubout
  2234. ;  ;;           C-u, C-x      line kill
  2235. ;  ;;           C-q, C-v      literal next
  2236. ;  
  2237. ;  (catch 'return-value
  2238. ;    (save-excursion
  2239. ;
  2240. ;      (let ((input-buffer (get-buffer-create (make-temp-name " *password*")))
  2241. ;            char hold-password help-form kill-ring)
  2242. ;
  2243. ;        (set-buffer input-buffer)
  2244. ;        ;; Don't add to undo ring.
  2245. ;        (buffer-disable-undo input-buffer)
  2246. ;
  2247. ;        (let ((cursor-in-echo-area t)
  2248. ;              (echo-keystrokes 0))
  2249. ;
  2250. ;          (unwind-protect
  2251. ;
  2252. ;              ;; BODYFORM 
  2253. ;              ;; Repeat until we get a `throw'.
  2254. ;              (while t
  2255. ;                (erase-buffer)
  2256. ;                (message prompt)
  2257. ;
  2258. ;                ;; Read string.
  2259. ;                (while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
  2260. ;                  (if (setq help-form
  2261. ;                            (cdr
  2262. ;                             (assq char
  2263. ;                                   '((?\C-h . (delete-char -1))
  2264. ;                                     (?\C-? . (delete-char -1))
  2265. ;                                     (?\C-u . (delete-region 1 (point)))
  2266. ;                                     (?\C-x . (delete-region 1 (point)))
  2267. ;                                     (?\C-q . (quoted-insert 1))
  2268. ;                                     (?\C-v . (quoted-insert 1))))))
  2269. ;                      (condition-case error-data
  2270. ;                          (eval help-form)
  2271. ;                        (error t))
  2272. ;                    ;; Just a plain character - insert into password buffer.
  2273. ;                    (insert char))
  2274. ;
  2275. ;                  ;; I think crypt-read-string-no-echo should echo asterisks.
  2276. ;                  ;; -- Jamie. How about periods like in ange-ftp? -- lrd
  2277. ;                  ;;
  2278. ;                  (message "%s%s" prompt (make-string (buffer-size) ?.)))
  2279. ;                
  2280. ;                ;; Do we have to confirm password?
  2281. ;                (cond
  2282. ;
  2283. ;                 ;; No confirmation requested - terminate.
  2284. ;                 ((not confirm)
  2285. ;                  (throw 'return-value (buffer-string)))
  2286. ;                 
  2287. ;                 ;; Can we compare (confirm) password values yet?
  2288. ;                 (hold-password
  2289. ;                  (if (string= hold-password (buffer-string))
  2290. ;                      ;; The two passwords match - terminate.
  2291. ;                      (throw 'return-value hold-password)
  2292. ;
  2293. ;                    ;; Mismatch - start over.
  2294. ;                    (progn
  2295. ;                      (message (concat prompt "[Mismatch. Start over]"))
  2296. ;                      (beep)
  2297. ;                      (sit-for 2)
  2298. ;                      (fillarray hold-password 0) ; destroy extra copy now
  2299. ;                      (setq hold-password nil))))
  2300. ;                 
  2301. ;                 ;; Store password and read again.
  2302. ;                 (t
  2303. ;                  (setq hold-password (buffer-string))
  2304. ;                  (message (concat prompt "[Retype to confirm]"))
  2305. ;                  (sit-for 2))))
  2306. ;            
  2307. ;            ;; UNWINDFORMS
  2308. ;            ;; Clean up.
  2309. ;            (set-buffer input-buffer)
  2310. ;            (set-buffer-modified-p nil)
  2311. ;            (buffer-disable-undo input-buffer) ; redundant, but why not be safe.
  2312. ;            (widen)
  2313. ;            (goto-char (point-min))
  2314. ;            (while (not (eobp)) (delete-char 1) (insert "*")) ; destroy now
  2315. ;            (kill-buffer input-buffer)))))))
  2316.  
  2317. (defun crypt-set-encryption-key (key &optional buffer)
  2318.  
  2319.   "Set the encryption KEY, a string, for current buffer or optionally BUFFER.
  2320. If buffer is in encrypted mode, then it is also marked as modified, since it
  2321. needs to be saved with the new key."
  2322.  
  2323.   (interactive
  2324.    (progn
  2325.      (barf-if-buffer-read-only)
  2326.      (list (crypt-read-string-no-echo
  2327.             (format "Encryption key for %s? [RET to ignore]: " (buffer-name))
  2328.             crypt-confirm-password))))
  2329.  
  2330.   ;; For security reasons we remove `(crypt-set-encryption-key "password")' 
  2331.   ;; from the `command-history' list if called interactively.
  2332.   (if (interactive-p)
  2333.       (setq command-history (cdr command-history)))
  2334.  
  2335.   (or buffer (setq buffer (current-buffer)))
  2336.  
  2337.   (save-excursion
  2338.     (set-buffer buffer)
  2339.     (if (equal key crypt-buffer-encryption-key)
  2340.         (message "Key is identical to original, no change.")
  2341.  
  2342.       (progn
  2343.     ;; jwz: destroy old string
  2344.     (if (and crypt-buffer-encryption-key
  2345.          (not (eq crypt-buffer-encryption-key key)))
  2346.         (fillarray crypt-buffer-encryption-key 0))
  2347.         (setq crypt-buffer-encryption-key key)
  2348.  
  2349.         ;; Don't touch the modify flag unless we're in `(crypt-encrypted-mode)'.
  2350.         (if crypt-buffer-save-encrypted
  2351.             (set-buffer-modified-p t))
  2352.  
  2353.     (crypt-reset-passwd-timer)
  2354.     ))))
  2355.  
  2356.  
  2357. ;;;; Install hooks and mode indicators.
  2358.  
  2359. ;;; Check if mode indicators are not already installed and then prepend them.
  2360. (and (not (assq 'crypt-buffer-save-encrypted minor-mode-alist))
  2361.      (setq minor-mode-alist (append crypt-minor-mode-alist minor-mode-alist)))
  2362.  
  2363. ;;; Install the hooks. 
  2364.  
  2365. ;;; If add-hook isn't already defined overwrite it with our own.
  2366. ;;; Note the `add-hook' function must take the optional APPEND argument.
  2367. (if (not (fboundp 'add-hook))
  2368.     ;; No add-hook found. 
  2369.     ;; Use `add-hook' from GNU Emacs v19.
  2370.     (defun add-hook (hook function &optional append)
  2371.       "Add to the value of HOOK the function FUNCTION.
  2372. FUNCTION is not added if already present.
  2373. FUNCTION is added (if necessary) at the beginning of the hook list
  2374. unless the optional argument APPEND is non-nil, in which case
  2375. FUNCTION is added at the end.
  2376.  
  2377. HOOK should be a symbol, and FUNCTION may be any valid function.  If
  2378. HOOK is void, it is first set to nil.  If HOOK's value is a single
  2379. function, it is changed to a list of functions."
  2380.       (or (boundp hook) (set hook nil))
  2381.       ;; If the hook value is a single function, turn it into a list.
  2382.       (let ((old (symbol-value hook)))
  2383.         (if (or (not (listp old)) (eq (car old) 'lambda))
  2384.             (set hook (list old))))
  2385.       (or (if (consp function)
  2386.               ;; Clever way to tell whether a given lambda-expression
  2387.               ;; is equal to anything in the hook.
  2388.               (let ((tail (assoc (cdr function) (symbol-value hook))))
  2389.                 (equal function tail))
  2390.             (memq function (symbol-value hook)))
  2391.           (set hook 
  2392.                (if append
  2393.                    (nconc (symbol-value hook) (list function))
  2394.                  (cons function (symbol-value hook)))))))
  2395.  
  2396. ;;; Attach ourselves to the find-file-hooks and find-file-not-found-hooks. 
  2397. (add-hook 'find-file-hooks 'crypt-find-file-hook)
  2398. (add-hook 'find-file-not-found-hooks 'crypt-find-file-hook)
  2399.  
  2400. ;; Take care when appending to write-file-hook.  User's version of add-hook
  2401. ;; may not have APPEND option.  If it fails then do it by hand.  I wish
  2402. ;; everyone would upgrade - lrd 8/31/93.
  2403. (condition-case err
  2404.     (add-hook 'write-file-hooks 'crypt-write-file-hook t) ; *must* append this
  2405.   (error
  2406.    ;; Do it by hand.  Not as robust as `add-hook'.
  2407.  
  2408.    ;; Contributed by Ken Laprade <laprade@trantor.harris-atd.com>
  2409.    ;; Really should use some sort of add-hook - 16 Feb 93 - KCL
  2410.    (or (and (listp write-file-hooks) (not (eq (car write-file-hooks) 'lambda)))
  2411.        (setq write-file-hooks (list write-file-hooks)))
  2412.  
  2413.    (cond
  2414.     ((not (memq 'crypt-write-file-hook write-file-hooks))
  2415.      ;; make this hook last on purpose
  2416.      (setq write-file-hooks (append write-file-hooks
  2417.                                     (list 'crypt-write-file-hook)))))))
  2418.  
  2419. ;; In order that the tables and key-binding correctly reflect user's
  2420. ;; preferences we add ourselves to the `after-init-hook' GNU Emacs v19 and
  2421. ;; Lucid Emacs v 19.8 (or later) or `term-setup-hook' in Lucid Emacs v 19.7
  2422. ;; (or earlier).  These are run *after* ~/.emacs and ../lisp/default.el are
  2423. ;; loaded.  Unfortunately, v18 does not have `after-init-hook' and
  2424. ;; `term-setup-hook' is just a single function.  It is a bit of a pain trying
  2425. ;; to work our functions in properly without overwriting the user's value.
  2426. ;; Therefore, we do nothing and hope they upgrade to v19 soon.
  2427.  
  2428. (cond ((boundp 'after-init-hook)
  2429.        ;; Must be running GNU Emacs v19 :->
  2430.        (add-hook 'after-init-hook 'crypt-rebuild-tables)
  2431.        (add-hook 'after-init-hook 'crypt-rebuild-minor-modes-alist)
  2432.        (add-hook 'after-init-hook 'crypt-bind-insert-file))
  2433.  
  2434.       ((and (string-match "^19" emacs-version) t)
  2435.        ;; Probably running Lucid Emacs v19.7 (or earlier) since it,
  2436.        ;; unfortunately, does not have `after-init-hook'.  Use
  2437.        ;; `term-setup-hook' instead and hope they upgrade to Lucid 19.8 or GNU
  2438.        ;; Emacs 19.
  2439.        (add-hook 'term-setup-hook 'crypt-rebuild-tables)
  2440.        (add-hook 'term-setup-hook 'crypt-rebuild-minor-modes-alist)
  2441.        (add-hook 'term-setup-hook 'crypt-bind-insert-file)))
  2442.  
  2443.  
  2444. ;;; Code for conditionally decoding/decrypting an inserted file
  2445.  
  2446. (defcustom crypt-bind-insert-file t
  2447.   "*t value means bind `crypt-insert-file' over `insert-file'.
  2448. If you wish to change this variable after crypt++ has been loaded then do
  2449. \\[crypt-bind-insert-file]."
  2450.   :type 'boolean
  2451.   :group 'crypt)
  2452.  
  2453. (defcustom crypt-auto-decode-insert nil
  2454.   "*t says decode/decrypt files that are inserted with `crypt-insert-file'.
  2455. nil says to ask before doing this."
  2456.   :type 'boolean
  2457.   :group 'crypt)
  2458.  
  2459. ;;; Bind `crypt-insert-file' over wherever `insert-file' is bound?
  2460. (defun crypt-bind-insert-file ()
  2461.  
  2462.   "Bind `crypt-insert-file' in place of `insert-file' or reverse based on
  2463. `crypt-bind-insert-file'.  Part of `after-init-hook'."
  2464.  
  2465.   (interactive)
  2466.  
  2467.   (if (interactive-p)
  2468.       (setq crypt-bind-insert-file
  2469.             (y-or-n-p "Bind crypt-insert-file over insert-file? ")))
  2470.  
  2471.   (if crypt-bind-insert-file
  2472.       (substitute-key-definition
  2473.        'insert-file 'crypt-insert-file (current-global-map))
  2474.     (substitute-key-definition
  2475.      'crypt-insert-file 'insert-file (current-global-map))))
  2476.  
  2477. ;;; Now call it.
  2478. (crypt-bind-insert-file)
  2479.  
  2480. ;;; crypt++ replacement for `insert-file'
  2481. (defun crypt-insert-file (filename)
  2482.   "Insert decoded/decrypted contents of file FILENAME into buffer after point.
  2483. Set mark after the inserted text.
  2484.  
  2485. This function is meant for the user to run interactively.
  2486. Don't call it from programs!  Use `insert-file-contents' instead.
  2487. \(Its calling sequence is different; see its documentation\).
  2488.  
  2489. This version will attempt to decrypt and/or decode file before inserting.
  2490. see variable `crypt-auto-decode-insert'."
  2491.   (interactive "fInsert file: ")
  2492.   (if (file-directory-p filename)
  2493.       (signal 'file-error (list "Opening input file" "file is a directory"
  2494.                                 filename)))
  2495.   (let ((tem (crypt-insert-file-contents filename))) ; use crypt++ to insert
  2496.     (push-mark (+ (point) (car (cdr tem))))))
  2497.  
  2498. (defun crypt-insert-file-contents (file)
  2499.  
  2500.   ;; Similar to `insert-file-contents' except decoding/decrypting of FILE
  2501.   ;; attempted.  See `crypt-insert-file' and `crypt-auto-decode-insert'
  2502.  
  2503.   (let (temp-buffer
  2504.         temp-list
  2505.         (crypt-auto-decode-buffer crypt-auto-decode-insert)
  2506.         (orig-buffer (current-buffer)))
  2507.     
  2508.     ;; Create a temporary buffer and decode and decrypt it.
  2509.     (save-excursion
  2510.       
  2511.       ;; Temporary buffer, use the same name as the file to be inserted.
  2512.       (setq temp-buffer (generate-new-buffer (file-name-nondirectory file)))
  2513.       (set-buffer temp-buffer)
  2514.       
  2515.       ;; Original insert-file-contents - save list.
  2516.       (setq temp-list (insert-file-contents file nil))
  2517.  
  2518.       ;; Make temp-buffer unmodified.
  2519.       (set-buffer-modified-p nil)
  2520.       
  2521.       ;; Need to set buffer name to file name for crypt++.
  2522.       (setq buffer-file-name file)
  2523.       
  2524.       ;; Decode and decrypt, if necessary.
  2525.       (crypt-find-file-hook)
  2526.       
  2527.       ;; Find the length of the file to be inserted. `insert-file-contents' 
  2528.       ;; returns it for the original encoded/encrypted file.
  2529.       (setcdr temp-list (cons (buffer-size) ()))
  2530.       
  2531.       ;; Now insert temp-buffer into original buffer.
  2532.       (set-buffer orig-buffer)
  2533.       (insert-buffer temp-buffer)
  2534.       
  2535.       ;; Kill the temporary buffer.
  2536.       (kill-buffer temp-buffer))
  2537.     
  2538.     ;; Return modified list from `insert-file-contents'.
  2539.     temp-list))
  2540.  
  2541.  
  2542. ;;;; BUG REPORTS
  2543.  
  2544. ;;; This section is provided for reports.
  2545. ;;; Using Barry A. Warsaw's reporter.el
  2546.  
  2547. (defconst crypt-version "2.82"
  2548.   "Revision number of crypt++.el -- handles compressed and encrypted files.
  2549. Type \\[crypt-submit-report] to send a bug report.  Available via anonymous
  2550. ftp in
  2551.  
  2552.    /roebling.poly.edu:/pub/lisp/crypt++.el.gz
  2553.    /archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/misc/crypt++.el.Z")
  2554.  
  2555. (defconst crypt-help-address
  2556.   "dodd@roebling.poly.edu"
  2557.   "Address(es) accepting submission of reports on crypt++.el.")
  2558.  
  2559. (defconst crypt-maintainer "Larry"
  2560.   "First name(s) of people accepting submission of reports on crypt++.el.")
  2561.  
  2562. (defconst crypt-file "crypt++.el"
  2563.   "Name of file containing emacs lisp code.")
  2564.  
  2565. (defconst crypt-variable-list
  2566.   (list 'shell-file-name ; These
  2567.         'load-path       ; are
  2568.         'exec-path       ; useful.
  2569.         'crypt-encryption-type 
  2570.         'crypt-encryption-file-extension
  2571.         'crypt-never-ever-decrypt
  2572.         'crypt-auto-write-buffer-encrypted
  2573.         'crypt-confirm-password
  2574.         'crypt-encrypted-disable-auto-save
  2575.         'crypt-auto-decode-buffer
  2576.         'crypt-auto-write-buffer
  2577.         'crypt-query-if-interactive
  2578.         'crypt-no-extension-implies-plain
  2579.         'crypt-freeze-vs-fortran
  2580.         'crypt-compact-vs-C++
  2581.         'crypt-ignored-filenames
  2582.         'crypt-default-encoding
  2583.         'crypt-encoded-disable-auto-save
  2584.         'crypt-bind-insert-file
  2585.         'crypt-auto-decode-insert
  2586.         'crypt-encoding-alist
  2587.         'crypt-encryption-alist
  2588.         )
  2589.   "List of variables to be appended to reports sent by `crypt-submit-report.'")
  2590.  
  2591. (defun crypt-submit-report ()
  2592.   "Submit via reporter.el a bug report on program.  Send report on `crypt-file'
  2593. version `crypt-version,' to `crypt-maintainer' at address `crypt-help-address'
  2594. listing variables `crypt-variable-list' in the message."
  2595.   (interactive)
  2596.  
  2597.   ;; In case we can't find reporter...
  2598.   (condition-case err
  2599.       (progn
  2600.         ;; Get it if we can.
  2601.         (require 'reporter)
  2602.  
  2603.         (reporter-submit-bug-report
  2604.          crypt-help-address                     ; address
  2605.          (concat crypt-file " " crypt-version)  ; pkgname
  2606.          crypt-variable-list                    ; varlist
  2607.          nil nil                                ; pre-hooks and post-hooks
  2608.          (concat "Yo! " crypt-maintainer ","))) ; salutation
  2609.  
  2610.     ;; ...fail gracefully.
  2611.     (error 
  2612.      (beep)
  2613.  
  2614.      ;; Do they have ange-ftp?
  2615.      (if (and (featurep 'ange-ftp)
  2616.               (y-or-n-p (concat "Sorry, reporter.el not found.  "
  2617.                                 "Can I ange-ftp it for you? ")))
  2618.  
  2619.          ;; Yes.  Then Ange-ftp a copy from roebling.
  2620.          (let ((ange-ftp-generate-anonymous-password t))
  2621.            ;; Might want to use the elisp archive official site?  But
  2622.            ;; then it would have to be uncompressed, etc. Ick!
  2623.            (find-file-other-window
  2624.             "/anonymous@roebling.poly.edu:/pub/reporter.el")
  2625.            (eval-current-buffer)
  2626.            (message (concat "Save reporter.el somewhere in `load-path' "
  2627.                             "and try again.")))
  2628.        
  2629.        ;; No ange-ftp.
  2630.        (message "Sorry, reporter.el not found.")
  2631.        (sit-for 3)
  2632.        (message (concat "Get it from archive.cis.ohio-state.edu "
  2633.                         "or roebling.poly.edu"))))))
  2634.  
  2635. ;;; Provide this package as crypt++ as well as crypt.
  2636. (provide 'crypt++)
  2637. (provide 'crypt)
  2638.  
  2639. ;;; crypt++.el ends here.
  2640.